#ifndef USRAI_H
#define USRAI_H

#include "AI.h"
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <ctime>
#include <unordered_set>
#include <string>
#include <queue>

extern tagGame tagUsrGame;
extern ins UsrIns;

#ifndef MAPPATTERN_SHALLOWS
#define MAPPATTERN_SHALLOWS 3
#endif

class UsrAI : public AI
{
public:
    // Game stage enumeration
    enum GameStage {
        STAGE_INITIAL,                  // Initial stage
        STAGE_BUILD_HOUSES,             // House building stage
        STAGE_POPULATION_GROWTH,        // Population growth stage
        STAGE_COLLECT_RESOURCES,        // Resource collection stage
        STAGE_BUILD_REQUIRED_BUILDINGS, // Build required buildings stage (docks and stocks)
        STAGE_UPGRADE_AGE,              // Age upgrade stage
        STAGE_BUILD_FISHING_BOAT,       // Fishing boat building stage
        STAGE_AFTER_UPGRADE,            // Tasks after upgrading to Tool Age
        STAGE_BUILD_WARSHIPS,           // Produce warships
        STAGE_EXPLORE,                  // Warships explore unknown areas
        STAGE_BUILD_ARMY,               // Build land army
        STAGE_LAND_INVASION,            // Land on enemy continent
        STAGE_COLLECT_GOLD              // Final stage: collect gold
    };

    // 新增探索相关变量
    static std::map<int, std::pair<int, int>> fleetPatrolTargets;
    static std::vector<std::pair<int, int>> explorationZones;
    static bool explorationZonesInitialized;

    // 新增运输相关变量
    static int villagersTransported;
    static int maxVillagersToTransport;

    // Core game state
    static tagInfo prevInfo;
    static int center_x, center_y;
    static bool centerInitialized;
    static std::set<std::pair<int, int>> occupiedPositions;
    static GameStage currentStage;

    // Building management
    static int houseCount;
    static int housesUnderConstruction;
    static const int TARGET_HOUSES = 4;
    static int houseBuilderSN;
    static int searchRadius;
    static int lastHouseX, lastHouseY;

    // Population management
    static int targetPopulation;
    static time_t lastVillagerProductionTime;
    static bool buildingHousesInProgressInPopulationStage;
    static std::unordered_set<int> ordinaryVillagers;

    // Required buildings
    static bool stockBuilt;
    static bool dockBuilt;
    static bool fishingBoatBuilt;
    static bool granaryBuilt;
    static bool marketBuilt;
    static bool armyCampBuilt;
    static bool rangeBuilt;
    static bool stableBuilt;
    static bool woodCuttingUpgraded;
    static bool toolUseUpgraded;
    static int dockBuilderSN;
    static bool dockBuilderReserved;
    static bool dockConstructionStarted;
    static int totalDocksPresent;
    static int completedDocksCount;
    static const int TARGET_DOCKS_NUM = 2;

    // Naval units
    static int fishingBoatCount;
    static const int TARGET_FISHING_BOATS = 4;
    static const int TARGET_BOATS_PER_DOCK = 2;
    static std::map<int, int> dockFishingBoatCount;

    static int warshipCount;
    static const int TARGET_WARSHIPS = 8;
    static const int TARGET_WARSHIPS_PER_DOCK = 4;
    static std::map<int, int> dockWarshipCount;

    static int transportShipCount;
    static const int TARGET_TRANSPORT_SHIPS = 1;
    static std::map<int, int> dockTransportShipCount;

    // Fleet management
    static std::vector<std::vector<int>> warshipFleets;
    static std::map<int, std::pair<int, int>> fleetExplorationTargets;
    static std::map<int, int> fleetAttackTargetsSN;
    static std::unordered_set<int> assignedWarships;
    static bool unifiedFleetMode;  // 统一舰队模式
    static std::pair<int, int> fleetExplorationCenter;  // 舰队探索中心
    static int fleetExplorationRadius;  // 当前探索半径
    static int currentEnemyTargetSN;  // 当前敌方目标
    static bool fleetInCombat;  // 舰队是否在战斗中
    static int combatStartFrame;  // 战斗开始帧
    static std::vector<std::pair<int, int>> exploredSectors;  // 已探索的扇区
    static bool fleetsFormed;

    // Land army management
    static int clubmanCount;
    static int slingerCount;
    static int bowmanCount;
    static int scoutCount;
    static const int TARGET_CLUBMAN = 10;
    static const int TARGET_SLINGER = 6;
    static const int TARGET_BOWMAN = 8;
    static const int TARGET_SCOUT = 4;
    static std::vector<int> landArmy;
    static std::unordered_set<int> boardedUnits;

    // Enemy continent exploration
    static bool enemyContinentFound;
    static int enemyContinentX, enemyContinentY;
    static std::vector<std::pair<int, int>> enemyLandPositions;
    static std::vector<std::pair<int, int>> landingPositions;
    static int selectedLandingX, selectedLandingY;

    // Gold mining
    static bool goldFound;
    static std::vector<std::pair<int, int>> goldPositions;
    static int goldCollected;
    static const int TARGET_GOLD = 2500;
    static std::unordered_set<int> goldMiners;
    static int transportedVillagers;
    static const int TARGET_GOLD_MINERS = 15;

    // Position search
    static int foundDockX, foundDockY;
    static bool dockPositionFound;
    static std::vector<std::pair<int, int>> fishPositions;
    static bool fishPositionsInitialized;

    // Post-upgrade management
    static int villagersToProduceAfterUpgrade;
    static int villagersProducedAfterUpgrade;
    static int existingStocksAtUpgrade;
    static const int TARGET_TOTAL_STOCKS = 2;
    static int toolAgeBuilderSN;
    static bool toolAgeBuilderAssigned;
    static int housesToBuildAfterUpgrade;
    static int housesBuiltAfterUpgrade;

    // Upgrade management
    static bool upgradeStarted;
    static bool ageUpgraded;
    static int upgradeBuilderSN;

    // Combat management
    static std::map<int, int> unitCombatTargets;
    static std::set<int> defeatedEnemies;
    static bool combatMode;

    static bool toolAgeInitialized;
    static int toolAgePhase;
    static bool toolAgeBuilderBusy;
    static int toolAgeStocksBuilt;
    static int toolAgeHousesBuilt;

    UsrAI(){this->id=0;}
    ~UsrAI(){}

private:
    // 新增函数声明
    bool findHomeCoastalLandPosition(int& x, int& y, const tagInfo& info);
    int getDistanceToNearestOcean(int x, int y, const tagInfo& info);
    bool findHomeCoastalPosition(int& x, int& y, const tagInfo& info);
    std::pair<int, int> getUnifiedFleetExplorationTarget(const tagInfo& info);
    void initializeExplorationZones(const tagInfo& info);
    bool findValidExplorationTarget(int fleetIndex, int& targetX, int& targetY, const tagInfo& info);
    std::pair<int, int> getPatrolTarget(int fleetIndex, const tagInfo& info);
    bool isValidOceanPosition(int x, int y, const tagInfo& info);
    void loadVillagersOntoTransports(const tagInfo& info);
    bool isPositionNearMapEdge(int x, int y);
    void initializeToolAge(const tagInfo& info);
    bool assignToolAgeBuilder(const tagInfo& info);
    void handleToolAgeConstruction(const tagInfo& info);
    bool checkToolAgeCompletion(const tagInfo& info);

    // Map utilities
    bool isLand(int type);
    bool isOcean(int type);
    bool isMapCellLand(int x, int y, const tagInfo& info);
    bool isCellAdjacentToLand(int cx, int cy, const tagInfo& info);
    int countAdjacentLand(int cx, int cy, const tagInfo& info);
    bool isPositionReachable(int x, int y, const tagInfo& info);

    // Building utilities
    bool isTooCloseToExistingDocks(int newDockX, int newDockY, const tagInfo& info);
    bool isPositionValidForBuilding(int x, int y, int width, int height, int buildingType, const tagInfo& info);
    bool isPositionValidForHouse(int x, int y, const tagInfo& info);
    bool findNearbyPosition(int& x, int& y, const tagInfo& info, int width = 2, int height = 2, int buildingType = -1);
    bool findBestStockPosition(int& x, int& y, const tagInfo& info);

    // Dock and coastal utilities
    bool findCoastalPositionNearCenter(int& x, int& y, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions);
    bool findDockPositionNearFish(int& x, int& y, const std::pair<int, int>& targetFishPos, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions);
    bool isDockNearFish(const std::pair<int, int>& fishPos, const tagInfo& info);
    bool findCoastalLandingPosition(int& x, int& y, const tagInfo& info);

    // Villager and unit management
    void assignTasksToVillagersWithLimits(const tagInfo& info, bool reserveOneIdleForDock);
    int findNearestResource(const tagFarmer& farmer, int resourceType, const tagInfo& info, const std::unordered_set<int>& excludedSNs);
    void produceVillagers(const tagInfo& info);

    // Naval unit management
    void assignFishingBoatsToFishResources(const tagInfo& info);
    void assignTransportShipsToShore(const tagInfo& info);
    void formWarshipFleets(const tagInfo& info);
    void manageTransportShipProduction(const tagInfo& info);

    // Stage handlers
    void initializeCenter(const tagInfo& info);
    void buildHousesPhase(const tagInfo& info);
    void populationGrowthPhase(const tagInfo& info);
    void collectResourcesPhase(const tagInfo& info);
    void buildRequiredBuildingsPhase(const tagInfo& info);
    void upgradeAgePhase(const tagInfo& info);
    void buildFishingBoatPhase(const tagInfo& info);
    void afterUpgradePhase(const tagInfo& info);
    void buildWarshipsPhase(const tagInfo& info);
    void explorePhase(const tagInfo& info);
    void buildArmyPhase(const tagInfo& info);
    void landInvasionPhase(const tagInfo& info);
    void collectGoldPhase(const tagInfo& info);

    // New utility functions
    void initializeFishPositions(const tagInfo& info);
    void scanForEnemyContinent(const tagInfo& info);
    void scanForGold(const tagInfo& info);
    void manageArmyProduction(const tagInfo& info);
    void loadArmyOntoTransports(const tagInfo& info);
    void commandInvasionFleet(const tagInfo& info);
    void manageCombat(const tagInfo& info);
    void transportVillagersToGold(const tagInfo& info);
    bool findSafeLandingPosition(int& x, int& y, const tagInfo& info);
    void protectGoldMiners(const tagInfo& info);

    // Main process function
    void processData() override;

    // API interface functions
    tagInfo getInfo(){return tagUsrGame.getInfo();}
    int AddToIns(instruction ins) override
    {
        UsrIns.lock.lock();
        ins.id=UsrIns.g_id;
        UsrIns.g_id++;
        UsrIns.instructions.push(ins);
        UsrIns.lock.unlock();
        return ins.id;
    }
    void clearInsRet() override{tagUsrGame.clearInsRet();}
};

#endif



#include "UsrAI.h"
#include <iostream>
#include <algorithm>
#include <ctime>
#include <sstream>
#include <unordered_set>
#include <string>
#include <climits>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <queue>

#define ACTION_OK 0

using namespace std;

// Global variables
tagGame tagUsrGame;
ins UsrIns;

// Static member initialization
bool UsrAI::unifiedFleetMode = true;
std::pair<int, int> UsrAI::fleetExplorationCenter = {64, 64};
int UsrAI::fleetExplorationRadius = 20;
int UsrAI::currentEnemyTargetSN = -1;
bool UsrAI::fleetInCombat = false;
int UsrAI::combatStartFrame = 0;
std::vector<std::pair<int, int>> UsrAI::exploredSectors;
std::map<int, std::pair<int, int>> UsrAI::fleetPatrolTargets;
std::vector<std::pair<int, int>> UsrAI::explorationZones;
bool UsrAI::explorationZonesInitialized = false;
int UsrAI::villagersTransported = 0;
int UsrAI::maxVillagersToTransport = 5;
tagInfo UsrAI::prevInfo;
int UsrAI::center_x = 0;
int UsrAI::center_y = 0;
bool UsrAI::centerInitialized = false;
set<pair<int, int>> UsrAI::occupiedPositions;
int UsrAI::houseCount = 0;
int UsrAI::housesUnderConstruction = 0;
UsrAI::GameStage UsrAI::currentStage = UsrAI::STAGE_INITIAL;
int UsrAI::searchRadius = 1;
int UsrAI::lastHouseX = -1;
int UsrAI::lastHouseY = -1;
int UsrAI::houseBuilderSN = -1;

int UsrAI::targetPopulation = 0;
time_t UsrAI::lastVillagerProductionTime = time(nullptr);
bool UsrAI::buildingHousesInProgressInPopulationStage = false;

bool UsrAI::stockBuilt = false;
bool UsrAI::dockBuilt = false;
bool UsrAI::fishingBoatBuilt = false;
bool UsrAI::ageUpgraded = false;
int UsrAI::dockBuilderSN = -1;
bool UsrAI::dockBuilderReserved = false;
bool UsrAI::dockConstructionStarted = false;
int UsrAI::totalDocksPresent = 0;
int UsrAI::completedDocksCount = 0;

int UsrAI::fishingBoatCount = 0;
std::map<int, int> UsrAI::dockFishingBoatCount;

int UsrAI::warshipCount = 0;
std::map<int, int> UsrAI::dockWarshipCount;

int UsrAI::transportShipCount = 0;
std::map<int, int> UsrAI::dockTransportShipCount;

std::vector<std::vector<int>> UsrAI::warshipFleets;
std::map<int, std::pair<int, int>> UsrAI::fleetExplorationTargets;
std::map<int, int> UsrAI::fleetAttackTargetsSN;
std::unordered_set<int> UsrAI::assignedWarships;
bool UsrAI::fleetsFormed = false;

int UsrAI::foundDockX = -1;
int UsrAI::foundDockY = -1;
bool UsrAI::dockPositionFound = false;

std::vector<std::pair<int, int>> UsrAI::fishPositions;
bool UsrAI::fishPositionsInitialized = false;
std::unordered_set<int> UsrAI::ordinaryVillagers;

int UsrAI::villagersToProduceAfterUpgrade = 0;
int UsrAI::villagersProducedAfterUpgrade = 0;
int UsrAI::existingStocksAtUpgrade = 0;

const int MAX_HOUSE_SEARCH_RADIUS = 15;

int UsrAI::toolAgeBuilderSN = -1;
bool UsrAI::toolAgeBuilderAssigned = false;
int UsrAI::housesToBuildAfterUpgrade = 4;
int UsrAI::housesBuiltAfterUpgrade = 0;

bool UsrAI::granaryBuilt = false;
bool UsrAI::marketBuilt = false;
bool UsrAI::armyCampBuilt = false;
bool UsrAI::rangeBuilt = false;
bool UsrAI::stableBuilt = false;
bool UsrAI::woodCuttingUpgraded = false;
bool UsrAI::toolUseUpgraded = false;

bool UsrAI::upgradeStarted = false;
int UsrAI::upgradeBuilderSN = -1;

int UsrAI::clubmanCount = 0;
int UsrAI::slingerCount = 0;
int UsrAI::bowmanCount = 0;
int UsrAI::scoutCount = 0;
std::vector<int> UsrAI::landArmy;
std::unordered_set<int> UsrAI::boardedUnits;

bool UsrAI::enemyContinentFound = false;
int UsrAI::enemyContinentX = -1;
int UsrAI::enemyContinentY = -1;
std::vector<std::pair<int, int>> UsrAI::enemyLandPositions;
std::vector<std::pair<int, int>> UsrAI::landingPositions;
int UsrAI::selectedLandingX = -1;
int UsrAI::selectedLandingY = -1;

bool UsrAI::goldFound = false;
std::vector<std::pair<int, int>> UsrAI::goldPositions;
int UsrAI::goldCollected = 0;
std::unordered_set<int> UsrAI::goldMiners;
int UsrAI::transportedVillagers = 0;

std::map<int, int> UsrAI::unitCombatTargets;
std::set<int> UsrAI::defeatedEnemies;
bool UsrAI::combatMode = false;

bool UsrAI::toolAgeInitialized = false;
int UsrAI::toolAgePhase = 0;
bool UsrAI::toolAgeBuilderBusy = false;
int UsrAI::toolAgeStocksBuilt = 0;
int UsrAI::toolAgeHousesBuilt = 0;

// Utility functions
bool UsrAI::isLand(int type) {
    return type == MAPPATTERN_GRASS || type == MAPPATTERN_SHALLOWS;
}

bool UsrAI::isOcean(int type) {
    return type == MAPPATTERN_OCEAN;
}

bool UsrAI::isMapCellLand(int x, int y, const tagInfo& info) {
    if (x < 0 || y < 0 || x >= 128 || y >= 128) {
        return false;
    }
    return this->isLand((*info.theMap)[x][y].type);
}

bool UsrAI::isCellAdjacentToLand(int cx, int cy, const tagInfo& info) {
    const int offsets[4][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1}
    };
    for (const auto& offset : offsets) {
        int adjX = cx + offset[0];
        int adjY = cy + offset[1];
        if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
            if (this->isMapCellLand(adjX, adjY, info)) {
                return true;
            }
        }
    }
    return false;
}

int UsrAI::countAdjacentLand(int cx, int cy, const tagInfo& info) {
    int count = 0;
    const int offsets[8][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
    };

    for (const auto& offset : offsets) {
        int adjX = cx + offset[0];
        int adjY = cy + offset[1];
        if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
            if (this->isMapCellLand(adjX, adjY, info)) {
                count++;
            }
        }
    }
    return count;
}

bool UsrAI::isPositionReachable(int x, int y, const tagInfo& info) {
    const int offsets[8][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
    };

    for (const auto& offset : offsets) {
        int checkX = x + offset[0];
        int checkY = y + offset[1];

        if (checkX >= 0 && checkY >= 0 && checkX < 128 && checkY < 128) {
            if (this->isLand((*info.theMap)[checkX][checkY].type) &&
                !occupiedPositions.count({checkX, checkY})) {
                return true;
            }
        }
    }
    return false;
}

bool UsrAI::isTooCloseToExistingDocks(int newDockX, int newDockY, const tagInfo& info) {
    const int MIN_DOCK_SEPARATION_EDGE_TO_EDGE = 10;
    const int DOCK_SIZE = 2;
    const int MAX_COORD_DIFF_FOR_CLOSENESS = DOCK_SIZE + MIN_DOCK_SEPARATION_EDGE_TO_EDGE;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK && b.Percent == 100) {
            int existingDockX = b.BlockDR;
            int existingDockY = b.BlockUR;

            int diffX = abs(newDockX - existingDockX);
            int diffY = abs(newDockY - existingDockY);

            if (diffX < MAX_COORD_DIFF_FOR_CLOSENESS && diffY < MAX_COORD_DIFF_FOR_CLOSENESS) {
                return true;
            }
        }
    }
    return false;
}

void UsrAI::initializeCenter(const tagInfo& info) {
    srand(time(NULL));

    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_CENTER) {
            center_x = building.BlockDR;
            center_y = building.BlockUR;
            centerInitialized = true;
            this->DebugText("Town Center at (" + to_string(center_x) + "," + to_string(center_y) + ")");

            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    occupiedPositions.insert({center_x + i, center_y + j});
                }
            }

            currentStage = STAGE_BUILD_HOUSES;
            this->DebugText("=== Starting House Building Stage ===");

            if (!dockPositionFound) {
                std::set<std::pair<int, int>> tempExcludedPositions;
                if (!fishPositionsInitialized) {
                    this->initializeFishPositions(info);
                }
                if (!fishPositions.empty() && this->findDockPositionNearFish(foundDockX, foundDockY, fishPositions[0], info, tempExcludedPositions)) {
                    dockPositionFound = true;
                }
            }

            if (!info.farmers.empty()) {
                houseBuilderSN = info.farmers[0].SN;
                for (size_t i = 0; i < info.farmers.size(); i++) {
                    if (info.farmers[i].SN != houseBuilderSN) {
                        ordinaryVillagers.insert(info.farmers[i].SN);
                    }
                }
            }
            break;
        }
    }
}

bool UsrAI::isPositionValidForBuilding(int x, int y, int width, int height, int buildingType, const tagInfo& info) {
    int firstHeight = -2;

    // 船坞特殊处理（必须建在海边）
    if (buildingType == BUILDING_DOCK) {
        if (width != 2 || height != 2) {
            return false;
        }

        // 船坞必须建在海洋上
        if (!(this->isOcean((*info.theMap)[x][y].type) &&
              this->isOcean((*info.theMap)[x + 1][y].type) &&
              this->isOcean((*info.theMap)[x][y + 1].type) &&
              this->isOcean((*info.theMap)[x + 1][y + 1].type))) {
            return false;
        }

        // 船坞必须靠近陆地
        bool hasFullSideAdjacentToLand = false;
        if (x - 1 >= 0 &&
            this->isMapCellLand(x - 1, y, info) &&
            this->isMapCellLand(x - 1, y + 1, info)) {
            hasFullSideAdjacentToLand = true;
        }
        if (!hasFullSideAdjacentToLand && x + 2 < 128 &&
            this->isMapCellLand(x + 2, y, info) &&
            this->isMapCellLand(x + 2, y + 1, info)) {
            hasFullSideAdjacentToLand = true;
        }
        if (!hasFullSideAdjacentToLand && y - 1 >= 0 &&
            this->isMapCellLand(x, y - 1, info) &&
            this->isMapCellLand(x + 1, y - 1, info)) {
            hasFullSideAdjacentToLand = true;
        }
        if (!hasFullSideAdjacentToLand && y + 2 < 128 &&
            this->isMapCellLand(x, y + 2, info) &&
            this->isMapCellLand(x + 1, y + 2, info)) {
            hasFullSideAdjacentToLand = true;
        }

        if (!hasFullSideAdjacentToLand) {
            return false;
        }

        // 检查是否与其他对象冲突
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                if (occupiedPositions.count({x + i, y + j})) {
                    return false;
                }
            }
        }

        return true;  // 船坞的特殊处理结束
    }

    // 其他建筑的处理
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            int checkX = x + i;
            int checkY = y + j;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) {
                return false;
            }

            // 必须是陆地
            if (!this->isLand((*info.theMap)[checkX][checkY].type) || (*info.theMap)[checkX][checkY].height == -1) {
                return false;
            }

            // 检查高度一致性
            if (firstHeight == -2) {
                firstHeight = (*info.theMap)[checkX][checkY].height;
            } else if ((*info.theMap)[checkX][checkY].height != firstHeight) {
                return false;
            }

            // 检查是否已被占用
            if (occupiedPositions.count({checkX, checkY})) {
                return false;
            }

            // 检查与现有建筑的冲突
            for (const auto& b : info.buildings) {
                int b_width, b_height;
                if (b.Type == BUILDING_DOCK) { b_width = 2; b_height = 2; }
                else if (b.Type == BUILDING_STOCK || b.Type == BUILDING_CENTER || b.Type == BUILDING_GRANARY ||
                         b.Type == BUILDING_ARMYCAMP || b.Type == BUILDING_MARKET || b.Type == BUILDING_FARM ||
                         b.Type == BUILDING_RANGE || b.Type == BUILDING_STABLE) { b_width = 3; b_height = 3; }
                else if (b.Type == BUILDING_HOME || b.Type == BUILDING_ARROWTOWER) { b_width = 2; b_height = 2; }
                else { b_width = 1; b_height = 1; }

                if (checkX >= b.BlockDR && checkX < (b.BlockDR + b_width) &&
                    checkY >= b.BlockUR && checkY < (b.BlockUR + b_height)) {
                    return false;
                }
            }

            // 检查与资源的冲突
            for (const auto& res : info.resources) {
                if (res.BlockDR == checkX && res.BlockUR == checkY) {
                    return false;
                }
            }
        }
    }

    // 新增：检查建筑是否太靠近海边（船坞除外）
    const int MIN_DISTANCE_FROM_OCEAN = 2;  // 至少离海2格

    // 检查建筑周围是否有海洋
    for (int dx = -MIN_DISTANCE_FROM_OCEAN; dx <= width + MIN_DISTANCE_FROM_OCEAN - 1; dx++) {
        for (int dy = -MIN_DISTANCE_FROM_OCEAN; dy <= height + MIN_DISTANCE_FROM_OCEAN - 1; dy++) {
            int checkX = x + dx;
            int checkY = y + dy;

            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                    // 发现海洋，这个位置太靠近海边
                    return false;
                }
            }
        }
    }

    // 房屋之间的最小间距检查
    if (buildingType == BUILDING_HOME) {
        for (int i = x - 1; i <= x + 2; ++i) {
            for (int j = y - 1; j <= y + 2; ++j) {
                for (const auto& b : info.buildings) {
                    if (b.Type == BUILDING_HOME) {
                        if (i >= b.BlockDR && i < b.BlockDR + 2 &&
                            j >= b.BlockUR && j < b.BlockUR + 2) {
                            return false;
                        }
                    }
                }
            }
        }
    }

    return true;
}

void UsrAI::afterUpgradePhase(const tagInfo& info) {
    this->DebugText("=== Post-Tool Age Phase ===");

    // 初始化工具时代
    if (!toolAgeInitialized) {
        initializeToolAge(info);
    }

    // 优先处理建造任务（在分配其他村民之前）
    this->DebugText("Attempting tool age construction...");
    handleToolAgeConstruction(info);

    // 生产村民（建造者已被保护）
    if (villagersProducedAfterUpgrade < villagersToProduceAfterUpgrade) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_CENTER && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_CENTER_CREATEFARMER_FOOD &&
                    (info.farmers.size() + info.armies.size()) < info.Human_MaxNum) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_CREATEFARMER);
                    if (ret > 0) {
                        villagersProducedAfterUpgrade++;
                        this->DebugText("Villager produced: " + to_string(villagersProducedAfterUpgrade) +
                                      "/" + to_string(villagersToProduceAfterUpgrade));
                    }
                    return; // 一次只生产一个
                }
            }
        }
    }

    // 最后分配其他村民任务（建造者已经被保护，不会被重新分配）
    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);

    // 检查是否完成，可以进入下一阶段
    if (checkToolAgeCompletion(info)) {
        // 释放建造者
        if (toolAgeBuilderSN != -1) {
            ordinaryVillagers.insert(toolAgeBuilderSN);
            toolAgeBuilderSN = -1;
            toolAgeBuilderAssigned = false;
            toolAgeBuilderBusy = false;
        }

        toolAgeInitialized = false; // 重置状态
        currentStage = STAGE_BUILD_WARSHIPS;
        this->DebugText("=== Entering Warship Building Stage ===");
    }
}
/*////////////////*/
// Part 2: Resource and Building Management

bool UsrAI::isPositionValidForHouse(int x, int y, const tagInfo& info) {
    return this->isPositionValidForBuilding(x, y, 2, 2, BUILDING_HOME, info);
}

bool UsrAI::findCoastalPositionNearCenter(int& x, int& y, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions) {
    const int MAX_RADIUS = 8;

    for (int r = 1; r <= MAX_RADIUS; r++) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                if (abs(i) != r && abs(j) != r) continue;

                int checkX = center_x + i;
                int checkY = center_y + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) {
                    continue;
                }

                if (excludedPositions.count({checkX, checkY})) {
                    continue;
                }

                if (this->isPositionValidForBuilding(checkX, checkY, 2, 2, BUILDING_DOCK, info)) {
                    if (this->isPositionReachable(checkX, checkY, info)) {
                        x = checkX;
                        y = checkY;
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

void UsrAI::initializeFishPositions(const tagInfo& info) {
    for (const auto& res : info.resources) {
        if (res.Type == RESOURCE_FISH) {
            fishPositions.push_back({res.BlockDR, res.BlockUR});
        }
    }
    std::sort(fishPositions.begin(), fishPositions.end(), [&](const std::pair<int, int>& a, const std::pair<int, int>& b) {
        int distA = abs(a.first - center_x) + abs(a.second - center_y);
        int distB = abs(b.first - center_x) + abs(b.second - center_y);
        return distA < distB;
    });
    fishPositionsInitialized = true;
}

bool UsrAI::isDockNearFish(const std::pair<int, int>& fishPos, const tagInfo& info) {
    const int DOCK_NEAR_FISH_RADIUS = 5;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK) {
            int minDist = INT_MAX;
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    int dockCornerX = b.BlockDR + i;
                    int dockCornerY = b.BlockUR + j;
                    int dist = abs(dockCornerX - fishPos.first) + abs(dockCornerY - fishPos.second);
                    if (dist < minDist) {
                        minDist = dist;
                    }
                }
            }
            if (minDist <= DOCK_NEAR_FISH_RADIUS) {
                return true;
            }
        }
    }
    return false;
}

bool UsrAI::findDockPositionNearFish(int& x, int& y, const std::pair<int, int>& targetFishPos, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions) {
    const int SEARCH_RADIUS_AROUND_FISH_FOR_DOCK = 8;

    int fishX = targetFishPos.first;
    int fishY = targetFishPos.second;

    int bestDockX = -1, bestDockY = -1;
    double maxConnectionScore = -1.0;

    for (int dx_dock = -SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; dx_dock <= SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; ++dx_dock) {
        for (int dy_dock = -SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; dy_dock <= SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; ++dy_dock) {
            int dockCandidateX = fishX + dx_dock;
            int dockCandidateY = fishY + dy_dock;

            if (excludedPositions.count({dockCandidateX, dockCandidateY})) {
                continue;
            }

            if (this->isTooCloseToExistingDocks(dockCandidateX, dockCandidateY, info)) {
                continue;
            }

            if (this->isPositionValidForBuilding(dockCandidateX, dockCandidateY, 2, 2, BUILDING_DOCK, info)) {
                if (this->isPositionReachable(dockCandidateX, dockCandidateY, info)) {
                    double currentConnectionScore = 0.0;
                    int numFullSidesAdjacent = 0;

                    if (dockCandidateX - 1 >= 0 &&
                        this->isMapCellLand(dockCandidateX - 1, dockCandidateY, info) &&
                        this->isMapCellLand(dockCandidateX - 1, dockCandidateY + 1, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX - 1, dockCandidateY, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX - 1, dockCandidateY + 1, info);
                    }
                    if (dockCandidateX + 2 < 128 &&
                        this->isMapCellLand(dockCandidateX + 2, dockCandidateY, info) &&
                        this->isMapCellLand(dockCandidateX + 2, dockCandidateY + 1, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 2, dockCandidateY, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 2, dockCandidateY + 1, info);
                    }
                    if (dockCandidateY - 1 >= 0 &&
                        this->isMapCellLand(dockCandidateX, dockCandidateY - 1, info) &&
                        this->isMapCellLand(dockCandidateX + 1, dockCandidateY - 1, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX, dockCandidateY - 1, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 1, dockCandidateY - 1, info);
                    }
                    if (dockCandidateY + 2 < 128 &&
                        this->isMapCellLand(dockCandidateX, dockCandidateY + 2, info) &&
                        this->isMapCellLand(dockCandidateX + 1, dockCandidateY + 2, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX, dockCandidateY + 2, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 1, dockCandidateY + 2, info);
                    }

                    currentConnectionScore += numFullSidesAdjacent * 500.0;

                    if (currentConnectionScore > maxConnectionScore) {
                        maxConnectionScore = currentConnectionScore;
                        bestDockX = dockCandidateX;
                        bestDockY = dockCandidateY;
                    }
                }
            }
        }
    }

    if (bestDockX != -1) {
        x = bestDockX;
        y = bestDockY;
        return true;
    }

    return false;
}

// Fixed villager assignment with complete logic
void UsrAI::assignTasksToVillagersWithLimits(const tagInfo& info, bool reserveOneIdleForDock) {
    // Remove dead villagers from the ordinaryVillagers set
    for (auto it = ordinaryVillagers.begin(); it != ordinaryVillagers.end(); ) {
        bool exists = false;
        for (const auto& farmer : info.farmers) {
            if (farmer.SN == *it) {
                exists = true;
                break;
            }
        }
        if (!exists) {
            this->DebugText("Removing dead villager #" + to_string(*it) + " from ordinary villagers set.");
            it = ordinaryVillagers.erase(it);
        }
        else {
            ++it;
        }
    }

    // Add newly produced or unassigned farmers to the ordinaryVillagers set
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort != 0) continue; // Only consider land villagers

        // Exclude specific builders
        if ((farmer.SN == houseBuilderSN && !dockBuilderReserved && currentStage == STAGE_BUILD_HOUSES) ||
            (farmer.SN == dockBuilderSN && dockBuilderReserved)) {
            continue;
        }
        if (currentStage == STAGE_AFTER_UPGRADE && toolAgeBuilderAssigned && farmer.SN == toolAgeBuilderSN) {
            continue;
        }
        if (upgradeStarted && farmer.SN == upgradeBuilderSN) {
            continue;
        }

        // Add to ordinary villagers if not already present
        if (ordinaryVillagers.find(farmer.SN) == ordinaryVillagers.end()) {
            ordinaryVillagers.insert(farmer.SN);
            this->DebugText("New villager #" + to_string(farmer.SN) + " added to ordinary villagers set.");
        }
    }

    // Count current workers by type
    int woodWorkers = 0;
    int foodWorkers = 0;
    int buildWorkers = 0;
    int idleCount = 0;
    int walkingCount = 0;

    for (const auto& farmer : info.farmers) {
        // Exclude dedicated builders from general task statistics
        if (currentStage == STAGE_AFTER_UPGRADE && toolAgeBuilderAssigned && farmer.SN == toolAgeBuilderSN) {
            continue;
        }
        if (upgradeStarted && farmer.SN == upgradeBuilderSN) {
            continue;
        }

        // Only count ordinary villagers
        if (ordinaryVillagers.count(farmer.SN) == 0) {
            continue;
        }

        if (farmer.NowState == HUMAN_STATE_IDLE) {
            idleCount++;
        } else if (farmer.NowState == HUMAN_STATE_WALKING) {
            walkingCount++;
        } else if (farmer.NowState == HUMAN_STATE_WORKING) {
            for (const auto& res : info.resources) {
                if (res.SN == farmer.WorkObjectSN) {
                    if (res.Type == RESOURCE_TREE) {
                        woodWorkers++;
                    } else if (res.Type == RESOURCE_GAZELLE ||
                               res.Type == RESOURCE_ELEPHANT ||
                               res.Type == RESOURCE_FISH) {
                        foodWorkers++;
                    }
                    break;
                }
            }
        }
    }

    this->DebugText("Ordinary Villager Task Stats: Idle=" + to_string(idleCount) +
                    " Walking=" + to_string(walkingCount) +
                    " Wood=" + to_string(woodWorkers) +
                    " Food=" + to_string(foodWorkers) +
                    " Build=" + to_string(buildWorkers));

    // 【关键修改】收集可分配任务的村民
    std::vector<const tagFarmer*> availableFarmers;
    for (const auto& farmer : info.farmers) {
        // Exclude dedicated builders
        if (currentStage == STAGE_AFTER_UPGRADE && toolAgeBuilderAssigned && farmer.SN == toolAgeBuilderSN) {
            continue;
        }
        if (upgradeStarted && farmer.SN == upgradeBuilderSN) {
            continue;
        }

        if (ordinaryVillagers.count(farmer.SN)) {
            // 包含IDLE状态的村民
            if (farmer.NowState == HUMAN_STATE_IDLE) {
                availableFarmers.push_back(&farmer);
            }
            // 【新增】包含WALKING状态且没有工作目标的村民（新生产的村民）
            else if (farmer.NowState == HUMAN_STATE_WALKING && farmer.WorkObjectSN == 0) {
                // 检查是否在市镇中心附近（新生产的村民特征）
                int distFromCenter = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (distFromCenter <= 4) {  // 在市镇中心4格范围内
                    availableFarmers.push_back(&farmer);
                    this->DebugText("Found new villager #" + to_string(farmer.SN) +
                                  " in WALKING state near Town Center, including for task assignment");
                }
            }
        }
    }

    // Sort by distance to Town Center (closer first for new villagers)
    std::sort(availableFarmers.begin(), availableFarmers.end(), [&](const tagFarmer* a, const tagFarmer* b) {
        int distA = abs(a->BlockDR - center_x) + abs(a->BlockUR - center_y);
        int distB = abs(b->BlockDR - center_x) + abs(b->BlockUR - center_y);
        return distA < distB; // 改为升序，优先处理离中心近的（新村民）
    });

    // Assign tasks to farmers
    for (const tagFarmer* farmer_ptr : availableFarmers) {
        const tagFarmer& current_farmer = *farmer_ptr;
        bool assignedThisTurn = false;
        std::unordered_set<int> villagerExcludedResources;

        // Prioritize food collection if not in Tool Age and food workers are below limit
        if (currentStage != STAGE_AFTER_UPGRADE &&
            !upgradeStarted &&
            foodWorkers < 2) // Target 2 food workers
        {
            int targetFoodSN = -1;

            // Try gazelle, then elephant, then fish
            targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_GAZELLE, info, villagerExcludedResources);
            if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_ELEPHANT, info, villagerExcludedResources);
            if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_FISH, info, villagerExcludedResources);

            if (targetFoodSN != -1) {
                int ret = HumanAction(farmer_ptr->SN, targetFoodSN);
                if (ret > 0) {
                    this->DebugText("Villager #" + to_string(farmer_ptr->SN) + " assigned to collect food.");
                    foodWorkers++;
                    assignedThisTurn = true;
                } else {
                    villagerExcludedResources.insert(targetFoodSN);
                    this->DebugText("Villager #" + to_string(farmer_ptr->SN) + " cannot reach food resource SN " + to_string(targetFoodSN));
                }
            }
        }

        // Assign wood collection if not already assigned
        if (!assignedThisTurn) {
            int attempts = 0;
            while (!assignedThisTurn && attempts < 5) {
                int targetTreeSN = this->findNearestResource(current_farmer, RESOURCE_TREE, info, villagerExcludedResources);
                if (targetTreeSN != -1) {
                    int ret = HumanAction(farmer_ptr->SN, targetTreeSN);
                    if (ret > 0) {
                        this->DebugText("Villager #" + to_string(farmer_ptr->SN) + " assigned to chop wood.");
                        woodWorkers++;
                        assignedThisTurn = true;
                    } else {
                        villagerExcludedResources.insert(targetTreeSN);
                        attempts++;
                    }
                } else {
                    this->DebugText("Villager #" + to_string(farmer_ptr->SN) + " found no trees to chop, will remain idle.");
                    break;
                }
            }
        }
    }
}

int UsrAI::findNearestResource(const tagFarmer& farmer, int resourceType, const tagInfo& info, const std::unordered_set<int>& excludedSNs) {
    int nearestSN = -1;
    double minDistance = -1;

    for (const auto& res : info.resources) {
        if (res.Type == resourceType && res.Cnt > 0 && excludedSNs.find(res.SN) == excludedSNs.end()) {
            double distance = abs(farmer.BlockDR - res.BlockDR) + abs(farmer.BlockUR - res.BlockUR);
            if (nearestSN == -1 || distance < minDistance) {
                minDistance = distance;
                nearestSN = res.SN;
            }
        }
    }
    return nearestSN;
}

void UsrAI::produceVillagers(const tagInfo& info) {
    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_CENTER && building.Percent == 100 && building.Project == 0) {
            if (info.Meat >= 50) {
                if (info.farmers.size() + info.armies.size() < info.Human_MaxNum) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_CREATEFARMER);
                    if (ret > 0) {
                        lastVillagerProductionTime = time(nullptr);
                    }
                }
            }
            break;
        }
    }
}

bool UsrAI::findNearbyPosition(int& x, int& y, const tagInfo& info, int width, int height, int buildingType) {
    int startX = center_x;
    int startY = center_y;

    // 从较小的半径开始搜索，但要避开海边
    const int MIN_START_RADIUS = 3;  // 从离中心3格开始，避免太靠近可能的海边

    for (int r = MIN_START_RADIUS; r <= MAX_HOUSE_SEARCH_RADIUS; ++r) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                if (r > MIN_START_RADIUS && abs(i) != r && abs(j) != r) continue;

                int checkX = startX + i;
                int checkY = startY + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128)
                    continue;

                // 使用改进后的验证函数（已包含海边检查）
                if (this->isPositionValidForBuilding(checkX, checkY, width, height, buildingType, info)) {
                    x = checkX;
                    y = checkY;
                    lastHouseX = x;
                    lastHouseY = y;

                    // 调试输出
                    this->DebugText("Found valid position for building at (" +
                                  to_string(x) + "," + to_string(y) +
                                  "), away from ocean");
                    return true;
                }
            }
        }
    }

    this->DebugText("Failed to find valid position away from ocean");
    return false;
}

// 在 UsrAI.cpp 中添加
int UsrAI::getDistanceToNearestOcean(int x, int y, const tagInfo& info) {
    int minDist = 999;

    // 搜索附近的海洋格子
    const int searchRadius = 10;
    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int checkX = x + dx;
            int checkY = y + dy;

            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                    int dist = abs(dx) + abs(dy);  // 曼哈顿距离
                    if (dist < minDist) {
                        minDist = dist;
                    }
                }
            }
        }
    }

    return minDist;
}

// 在 UsrAI.h 的 private 部分添加声明
int getDistanceToNearestOcean(int x, int y, const tagInfo& info);
bool UsrAI::findBestStockPosition(int& x, int& y, const tagInfo& info) {
    int bestX = -1, bestY = -1;
    int maxTreeCount = -1;
    const int searchRadius = 10;  // 稍微增大搜索范围，因为要避开海边

    std::vector<std::pair<int, int>> treePositions;
    for (const auto& res : info.resources) {
        if (res.Type == RESOURCE_TREE && res.Cnt > 0) {
            treePositions.push_back({res.BlockDR, res.BlockUR});
        }
    }

    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int candidateX = center_x + dx;
            int candidateY = center_y + dy;

            if (candidateX < 0 || candidateY < 0 || candidateX >= 128 || candidateY >= 128) {
                continue;
            }

            // 使用更新后的验证函数（包含海边检查）
            if (isPositionValidForBuilding(candidateX, candidateY, 3, 3, BUILDING_STOCK, info)) {
                // 额外检查：确保不会太靠近海边
                bool tooCloseToOcean = false;
                const int SAFE_DISTANCE = 3;  // 仓库离海至少3格

                for (int checkX = candidateX - SAFE_DISTANCE;
                     checkX <= candidateX + 3 + SAFE_DISTANCE; checkX++) {
                    for (int checkY = candidateY - SAFE_DISTANCE;
                         checkY <= candidateY + 3 + SAFE_DISTANCE; checkY++) {
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                tooCloseToOcean = true;
                                break;
                            }
                        }
                    }
                    if (tooCloseToOcean) break;
                }

                if (tooCloseToOcean) {
                    continue;  // 跳过太靠近海边的位置
                }

                // 计算附近的树木数量
                int treeCount = 0;
                for (const auto& tree : treePositions) {
                    double distance = sqrt(pow(candidateX - tree.first, 2) + pow(candidateY - tree.second, 2));
                    if (distance <= 5.0) {
                        treeCount++;
                    }
                }

                if (treeCount > maxTreeCount) {
                    maxTreeCount = treeCount;
                    bestX = candidateX;
                    bestY = candidateY;
                }
            }
        }
    }

    if (bestX != -1 && bestY != -1) {
        x = bestX;
        y = bestY;
        this->DebugText("Found stock position at (" + to_string(x) + "," + to_string(y) +
                      ") with " + to_string(maxTreeCount) + " trees nearby, away from ocean");
        return true;
    }

    this->DebugText("Failed to find suitable stock position away from ocean");
    return false;
}

// Part 3: Game Stage Handlers

void UsrAI::collectResourcesPhase(const tagInfo& info) {
    this->DebugText("Resource Collection | Wood: " + to_string(info.Wood) +
              " | Food: " + to_string(info.Meat) +
              " | Stone: " + to_string(info.Stone));

    if (!fishPositionsInitialized) {
        this->initializeFishPositions(info);
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::populationGrowthPhase(const tagInfo& info) {
    int currentPopulation = info.farmers.size() + info.armies.size();
    int populationCapacity = info.Human_MaxNum;

    this->DebugText("Population Growth | Current: " + to_string(currentPopulation) +
                    "/" + to_string(populationCapacity) +
                    " | Target: " + to_string(targetPopulation));

    this->produceVillagers(info);

    if (currentPopulation >= targetPopulation && houseCount == TARGET_HOUSES && housesUnderConstruction == 0) {
        this->DebugText("=== Population target reached, entering Required Buildings ===");
        currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;

        if (houseBuilderSN != -1 && dockBuilderSN == -1) {
            dockBuilderSN = houseBuilderSN;
            dockBuilderReserved = true;
            if (ordinaryVillagers.count(dockBuilderSN)) {
                ordinaryVillagers.erase(dockBuilderSN);
            }
        }
        return;
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::buildRequiredBuildingsPhase(const tagInfo& info) {
    this->DebugText("Required Buildings | Stock: " + string(stockBuilt ? "Done" : "Pending") +
              " | Docks: " + to_string(completedDocksCount) + "/" + to_string(TARGET_DOCKS_NUM));

    int docksUnderConstruction = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK && b.Percent < 100) {
            docksUnderConstruction++;
        }
    }

    if (completedDocksCount >= TARGET_DOCKS_NUM) {
        currentStage = STAGE_BUILD_FISHING_BOAT;
        this->DebugText("=== All docks built, entering Fishing Boat Stage ===");
        if (dockBuilderSN != -1 && ordinaryVillagers.find(dockBuilderSN) == ordinaryVillagers.end()) {
            ordinaryVillagers.insert(dockBuilderSN);
            dockBuilderReserved = false;
        }
        return;
    }

    if (completedDocksCount < TARGET_DOCKS_NUM && docksUnderConstruction == 0) {
        tagFarmer* builderFarmer = nullptr;

        if (dockBuilderSN != -1) {
            for (const auto& farmer : info.farmers) {
                if (farmer.SN == dockBuilderSN && farmer.FarmerSort == 0) {
                    builderFarmer = const_cast<tagFarmer*>(&farmer);
                    break;
                }
            }
        }

        if (builderFarmer == nullptr && dockBuilderSN != -1) {
            bool isBuilderBusy = false;
            for (const auto& farmer : info.farmers) {
                if (farmer.SN == dockBuilderSN && farmer.NowState != HUMAN_STATE_IDLE) {
                    isBuilderBusy = true;
                    break;
                }
            }

            if (!isBuilderBusy) {
                dockBuilderSN = -1;
                dockBuilderReserved = false;
            }
        }

        if (builderFarmer == nullptr && dockBuilderSN == -1) {
            for (const auto& farmer : info.farmers) {
                if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                    if (farmer.SN == houseBuilderSN && !dockBuilderReserved) {
                        continue;
                    }
                    builderFarmer = const_cast<tagFarmer*>(&farmer);
                    dockBuilderSN = farmer.SN;
                    dockBuilderReserved = true;
                    ordinaryVillagers.erase(dockBuilderSN);
                    break;
                }
            }
        }

        if (builderFarmer != nullptr) {
            int dockX = -1, dockY = -1;
            std::set<std::pair<int, int>> failedDockAttemptsThisCall;
            bool positionFound = false;

            for (const auto& fishPos : fishPositions) {
                if (this->isDockNearFish(fishPos, info)) {
                    continue;
                }

                positionFound = this->findDockPositionNearFish(dockX, dockY, fishPos, info, failedDockAttemptsThisCall);
                if (positionFound) {
                    if (info.Wood >= BUILD_DOCK_WOOD) {
                        int ret = HumanBuild(builderFarmer->SN, BUILDING_DOCK, dockX, dockY);
                        if (ret > 0) {
                            dockConstructionStarted = true;
                            for (int i = 0; i < 2; i++) {
                                for (int j = 0; j < 2; j++) {
                                    occupiedPositions.insert({dockX+i, dockY+j});
                                }
                            }
                            return;
                        } else {
                            failedDockAttemptsThisCall.insert({dockX, dockY});
                        }
                    }
                    break;
                }
            }
        }
    }

    if (!stockBuilt && completedDocksCount >= TARGET_DOCKS_NUM) {
        int buildX, buildY;
        if (this->findBestStockPosition(buildX, buildY, info)) {
            if (info.Wood >= BUILD_STOCK_WOOD) {
                tagFarmer* builderForStock = nullptr;
                for (const auto& farmer : info.farmers) {
                    if (ordinaryVillagers.count(farmer.SN) && farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        builderForStock = const_cast<tagFarmer*>(&farmer);
                        break;
                    }
                }

                if (builderForStock != nullptr) {
                    int ret = HumanBuild(builderForStock->SN, BUILDING_STOCK, buildX, buildY);
                    if (ret > 0) {
                        for (int i = 0; i < 3; i++) {
                            for (int j = 0; j < 3; j++) {
                                occupiedPositions.insert({buildX+i, buildY+j});
                            }
                        }
                    }
                }
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
}

void UsrAI::upgradeAgePhase(const tagInfo& info) {
    this->DebugText("Age Upgrade | Current: " + to_string(info.civilizationStage));

    if (info.civilizationStage == CIVILIZATION_TOOLAGE) {
        ageUpgraded = true;
        currentStage = STAGE_AFTER_UPGRADE;
        villagersToProduceAfterUpgrade = 6;
        villagersProducedAfterUpgrade = 0;

        existingStocksAtUpgrade = 0;
        for (const auto& b : info.buildings) {
            if (b.Type == BUILDING_STOCK) {
                existingStocksAtUpgrade++;
            }
        }
        housesToBuildAfterUpgrade = TARGET_HOUSES + 4;
        this->DebugText("=== Age upgraded, entering Post-Tool Age ===");
        return;
    }

    this->DebugText("Need 500 food. Current: " + to_string(info.Meat));

    if (info.Meat >= 500) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_CENTER) {
                if (building.Percent == 100 && building.Project == 0) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_UPGRADE);
                    if (ret > 0) {
                        this->DebugText("Age upgrade started");
                    }
                    break;
                }
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
}

void UsrAI::initializeToolAge(const tagInfo& info) {
    if (toolAgeInitialized) return;

    this->DebugText("=== Initializing Tool Age Construction ===");

    // 统计现有建筑
    toolAgeStocksBuilt = 0;
    toolAgeHousesBuilt = 0;
    granaryBuilt = false;
    marketBuilt = false;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) {
            toolAgeStocksBuilt++;
        }
        if (b.Type == BUILDING_HOME && b.Percent == 100) {
            toolAgeHousesBuilt++;
        }
        if (b.Type == BUILDING_GRANARY && b.Percent == 100) {
            granaryBuilt = true;
        }
        if (b.Type == BUILDING_MARKET && b.Percent == 100) {
            marketBuilt = true;
        }
    }

    // 设置初始阶段
    if (toolAgeStocksBuilt < TARGET_TOTAL_STOCKS) {
        toolAgePhase = 0; // 建造仓库
    } else if (toolAgeHousesBuilt < TARGET_HOUSES + 4) {
        toolAgePhase = 1; // 建造房屋
    } else if (!granaryBuilt || !marketBuilt) {
        toolAgePhase = 2; // 建造特殊建筑
    } else {
        toolAgePhase = 3; // 科技升级
    }

    toolAgeInitialized = true;
    toolAgeBuilderSN = -1;
    toolAgeBuilderBusy = false;

    this->DebugText("Tool Age Phase: " + to_string(toolAgePhase) +
                    " | Stocks: " + to_string(toolAgeStocksBuilt) +
                    " | Houses: " + to_string(toolAgeHousesBuilt));
}

bool UsrAI::assignToolAgeBuilder(const tagInfo& info) {
    // 检查当前建造者是否还有效
    if (toolAgeBuilderSN != -1) {
        bool builderExists = false;
        bool builderIdle = false;

        for (const auto& farmer : info.farmers) {
            if (farmer.SN == toolAgeBuilderSN && farmer.FarmerSort == 0) {
                builderExists = true;
                // 允许 WALKING 状态的村民继续作为建造者
                if (farmer.NowState == HUMAN_STATE_IDLE || farmer.NowState == HUMAN_STATE_WALKING) {
                    builderIdle = true;
                }
                break;
            }
        }

        if (builderExists && !builderIdle) {
            this->DebugText("Builder #" + to_string(toolAgeBuilderSN) + " is busy");
            return false; // 建造者忙碌中
        }

        if (!builderExists) {
            this->DebugText("Builder #" + to_string(toolAgeBuilderSN) + " no longer exists");
            toolAgeBuilderSN = -1;
            toolAgeBuilderBusy = false;
            toolAgeBuilderAssigned = false;
        } else if (builderIdle) {
            this->DebugText("Builder #" + to_string(toolAgeBuilderSN) + " is ready");
            return true; // 建造者空闲，可以工作
        }
    }

    // 分配新的建造者 - 改进的逻辑
    if (toolAgeBuilderSN == -1) {
        std::vector<int> candidates;

        // 收集所有可能的候选者（包括 IDLE 和 WALKING 状态）
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0 &&
                (farmer.NowState == HUMAN_STATE_IDLE || farmer.NowState == HUMAN_STATE_WALKING)) {
                candidates.push_back(farmer.SN);
            }
        }

        this->DebugText("Found " + to_string(candidates.size()) + " builder candidates");

        if (!candidates.empty()) {
            // 优先选择不在普通村民集合中的
            for (int candidateSN : candidates) {
                if (ordinaryVillagers.find(candidateSN) == ordinaryVillagers.end()) {
                    toolAgeBuilderSN = candidateSN;
                    toolAgeBuilderBusy = false;
                    toolAgeBuilderAssigned = true;
                    this->DebugText("Assigned Tool Age builder (non-ordinary): #" + to_string(toolAgeBuilderSN));
                    return true;
                }
            }

            // 如果没找到，强制征用一个普通村民
            int selectedSN = candidates[0]; // 选择第一个候选者
            toolAgeBuilderSN = selectedSN;
            ordinaryVillagers.erase(selectedSN); // 从普通村民中移除
            toolAgeBuilderBusy = false;
            toolAgeBuilderAssigned = true;
            this->DebugText("Forced assignment Tool Age builder: #" + to_string(toolAgeBuilderSN));
            return true;
        } else {
            this->DebugText("No suitable builder candidates found");
        }
    }

    return toolAgeBuilderSN != -1;
}

void UsrAI::handleToolAgeConstruction(const tagInfo& info) {
    this->DebugText("=== handleToolAgeConstruction Phase " + to_string(toolAgePhase) + " ===");

    if (!assignToolAgeBuilder(info)) {
        this->DebugText("Failed to assign tool age builder");
        return;
    }

    // 关键修改：即使建造者忙碌，也要检查是否应该进入下一阶段
    // 先检查阶段完成情况，可能需要更新阶段
    checkToolAgeCompletion(info);

    if (toolAgeBuilderBusy) {
        this->DebugText("Tool age builder #" + to_string(toolAgeBuilderSN) + " is busy");
        return;
    }

    this->DebugText("Tool age builder ready: #" + to_string(toolAgeBuilderSN));

    // 验证建造者状态
    const tagFarmer* builder = nullptr;
    for (const auto& farmer : info.farmers) {
        if (farmer.SN == toolAgeBuilderSN) {
            builder = &farmer;
            this->DebugText("Builder state: " + to_string(farmer.NowState) +
                          " at (" + to_string(farmer.BlockDR) + "," + to_string(farmer.BlockUR) + ")");
            break;
        }
    }

    if (!builder) {
        this->DebugText("Builder not found in farmer list!");
        toolAgeBuilderSN = -1;
        toolAgeBuilderAssigned = false;
        return;
    }

    // 只有真正空闲的建造者才能执行建造任务
    if (builder->NowState != HUMAN_STATE_IDLE) {
        this->DebugText("Builder not idle, state: " + to_string(builder->NowState));
        return;
    }

    // 根据当前阶段执行对应的建造任务
    int buildX = -1, buildY = -1;
    int buildingType = -1;
    int requiredWood = 0;
    bool canBuild = false;

    switch (toolAgePhase) {
        case 0: // 建造仓库阶段
            this->DebugText("Phase 0: Building stocks (" + to_string(toolAgeStocksBuilt) + "/" + to_string(TARGET_TOTAL_STOCKS) + ")");
            if (toolAgeStocksBuilt < TARGET_TOTAL_STOCKS) {
                if (findBestStockPosition(buildX, buildY, info)) {
                    buildingType = BUILDING_STOCK;
                    requiredWood = BUILD_STOCK_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                    this->DebugText("Stock position found at (" + to_string(buildX) + "," + to_string(buildY) +
                                  "), Wood: " + to_string(info.Wood) + "/" + to_string(requiredWood));
                } else {
                    this->DebugText("No valid position found for stock");
                }
            }
            break;

        case 1: // 建造房屋阶段
            this->DebugText("Phase 1: Building houses (" + to_string(toolAgeHousesBuilt) + "/" + to_string(TARGET_HOUSES + 4) + ")");
            if (toolAgeHousesBuilt < TARGET_HOUSES + 4) {
                if (findNearbyPosition(buildX, buildY, info, 2, 2, BUILDING_HOME)) {
                    buildingType = BUILDING_HOME;
                    requiredWood = BUILD_HOUSE_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                    this->DebugText("House position found at (" + to_string(buildX) + "," + to_string(buildY) +
                                  "), Wood: " + to_string(info.Wood) + "/" + to_string(requiredWood));
                } else {
                    this->DebugText("No valid position found for house");
                }
            }
            break;

        case 2: // 建造特殊建筑阶段
            if (!granaryBuilt) {
                this->DebugText("Phase 2: Building granary");
                if (findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_GRANARY)) {
                    buildingType = BUILDING_GRANARY;
                    requiredWood = BUILD_GRANARY_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                    this->DebugText("Granary position found at (" + to_string(buildX) + "," + to_string(buildY) + ")");
                }
            } else if (!marketBuilt) {
                this->DebugText("Phase 2: Building market");
                if (findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_MARKET)) {
                    buildingType = BUILDING_MARKET;
                    requiredWood = BUILD_MARKET_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                    this->DebugText("Market position found at (" + to_string(buildX) + "," + to_string(buildY) + ")");
                }
            }
            break;

        case 3: // 科技升级阶段
            this->DebugText("Phase 3: Technology upgrades");
            if (!woodCuttingUpgraded) {
                for (const auto& building : info.buildings) {
                    if (building.Type == BUILDING_MARKET && building.Percent == 100 && building.Project == 0) {
                        if (info.Meat >= BUILDING_MARKET_WOOD_UPGRADE_FOOD &&
                            info.Wood >= BUILDING_MARKET_WOOD_UPGRADE_WOOD) {
                            int ret = BuildingAction(building.SN, BUILDING_MARKET_WOOD_UPGRADE);
                            if (ret > 0) {
                                woodCuttingUpgraded = true;
                                this->DebugText("Wood cutting upgrade started");
                                return;
                            }
                        } else {
                            this->DebugText("Need resources for wood upgrade - Food: " +
                                          to_string(BUILDING_MARKET_WOOD_UPGRADE_FOOD) + "/" + to_string(info.Meat) +
                                          ", Wood: " + to_string(BUILDING_MARKET_WOOD_UPGRADE_WOOD) + "/" + to_string(info.Wood));
                        }
                        break;
                    }
                }
            }
            return; // 科技升级不需要建造
    }

    // 执行建造
    if (canBuild && buildX != -1 && buildY != -1 && buildingType != -1) {
        this->DebugText("Attempting to build type " + to_string(buildingType) +
                      " at (" + to_string(buildX) + "," + to_string(buildY) + ")");

        int ret = HumanBuild(toolAgeBuilderSN, buildingType, buildX, buildY);
        if (ret > 0) {
            toolAgeBuilderBusy = true;

            // 标记占用位置
            int size = (buildingType == BUILDING_HOME) ? 2 : 3;
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    occupiedPositions.insert({buildX + i, buildY + j});
                }
            }

            this->DebugText("Construction started successfully: " + to_string(buildingType) +
                          " at (" + to_string(buildX) + "," + to_string(buildY) + ")");
        } else {
            this->DebugText("Construction failed with error code: " + to_string(ret));
        }
    } else if (!canBuild && buildX != -1) {
        this->DebugText("Not enough resources for construction - need " + to_string(requiredWood) + " wood, have " + to_string(info.Wood));
    } else {
        this->DebugText("No valid construction position found for current phase");
    }
}

bool UsrAI::checkToolAgeCompletion(const tagInfo& info) {
    // 更新建筑计数
    int previousStocksBuilt = toolAgeStocksBuilt;
    int previousHousesBuilt = toolAgeHousesBuilt;
    bool previousGranaryBuilt = granaryBuilt;
    bool previousMarketBuilt = marketBuilt;

    toolAgeStocksBuilt = 0;
    toolAgeHousesBuilt = 0;
    granaryBuilt = false;
    marketBuilt = false;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) {
            toolAgeStocksBuilt++;
        }
        if (b.Type == BUILDING_HOME && b.Percent == 100) {
            toolAgeHousesBuilt++;
        }
        if (b.Type == BUILDING_GRANARY && b.Percent == 100) {
            granaryBuilt = true;
        }
        if (b.Type == BUILDING_MARKET && b.Percent == 100) {
            marketBuilt = true;
        }
    }

    // 检测建筑完成并更新阶段
    bool shouldAdvancePhase = false;

    switch (toolAgePhase) {
        case 0: // 仓库阶段
            if (toolAgeStocksBuilt > previousStocksBuilt) {
                this->DebugText("Stock completed! Stocks: " + to_string(toolAgeStocksBuilt) + "/" + to_string(TARGET_TOTAL_STOCKS));
            }
            if (toolAgeStocksBuilt >= TARGET_TOTAL_STOCKS) {
                toolAgePhase = 1;
                toolAgeBuilderBusy = false; // 重置建造者状态
                shouldAdvancePhase = true;
                this->DebugText("=== Tool Age Phase 1: Building Houses ===");
            }
            break;

        case 1: // 房屋阶段
            if (toolAgeHousesBuilt > previousHousesBuilt) {
                this->DebugText("House completed! Houses: " + to_string(toolAgeHousesBuilt) + "/" + to_string(TARGET_HOUSES + 4));
            }
            if (toolAgeHousesBuilt >= TARGET_HOUSES + 4) {
                toolAgePhase = 2;
                toolAgeBuilderBusy = false; // 重置建造者状态
                shouldAdvancePhase = true;
                this->DebugText("=== Tool Age Phase 2: Special Buildings ===");
            }
            break;

        case 2: // 特殊建筑阶段
            if (granaryBuilt && !previousGranaryBuilt) {
                this->DebugText("Granary completed!");
                toolAgeBuilderBusy = false; // 重置建造者状态
            }
            if (marketBuilt && !previousMarketBuilt) {
                this->DebugText("Market completed!");
                toolAgeBuilderBusy = false; // 重置建造者状态
            }
            if (granaryBuilt && marketBuilt) {
                toolAgePhase = 3;
                toolAgeBuilderBusy = false; // 重置建造者状态
                shouldAdvancePhase = true;
                this->DebugText("=== Tool Age Phase 3: Technology Upgrades ===");
            }
            break;
    }

    // 如果阶段发生变化，输出当前状态
    if (shouldAdvancePhase) {
        this->DebugText("Phase advanced to " + to_string(toolAgePhase) +
                      " | Stocks: " + to_string(toolAgeStocksBuilt) +
                      " | Houses: " + to_string(toolAgeHousesBuilt) +
                      " | Granary: " + (granaryBuilt ? "Yes" : "No") +
                      " | Market: " + (marketBuilt ? "Yes" : "No"));
    }

    // 检查是否完成所有任务
    bool allComplete = (toolAgeStocksBuilt >= TARGET_TOTAL_STOCKS) &&
                      (toolAgeHousesBuilt >= TARGET_HOUSES + 4) &&
                      granaryBuilt && marketBuilt && woodCuttingUpgraded;

    if (allComplete) {
        this->DebugText("=== Tool Age Construction Complete ===");

        // 释放建造者
        if (toolAgeBuilderSN != -1) {
            ordinaryVillagers.insert(toolAgeBuilderSN);
            toolAgeBuilderSN = -1;
            toolAgeBuilderBusy = false;
            toolAgeBuilderAssigned = false;
        }

        return true;
    }

    return false;
}

// Part 4: House Building and Fishing Boat Phases

void UsrAI::buildHousesPhase(const tagInfo& info) {
    this->DebugText("House Building | Built: " + to_string(houseCount) +
                    "/" + to_string(TARGET_HOUSES) +
                    " | Under Construction: " + to_string(housesUnderConstruction));

    if (houseCount >= 1) {
        this->produceVillagers(info);
    }

    if (houseCount == TARGET_HOUSES && housesUnderConstruction == 0) {
        if (completedDocksCount < TARGET_DOCKS_NUM && info.Wood >= BUILD_DOCK_WOOD) {
            currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;
            this->DebugText("=== Houses complete, entering Required Buildings ===");
        } else {
            currentStage = STAGE_POPULATION_GROWTH;
            targetPopulation = 10;
            this->DebugText("=== Houses complete, entering Population Growth ===");
        }

        if (houseBuilderSN != -1 && dockBuilderSN == -1) {
            dockBuilderSN = houseBuilderSN;
            dockBuilderReserved = true;
            if (ordinaryVillagers.count(dockBuilderSN)) {
                ordinaryVillagers.erase(dockBuilderSN);
            }
        }
        return;
    }

    if (houseCount + housesUnderConstruction < TARGET_HOUSES) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 2, 2, BUILDING_HOME)) {
            if (info.Wood >= BUILD_HOUSE_WOOD) {
                tagFarmer* builder = nullptr;

                for (const auto& farmer : info.farmers) {
                    if (farmer.SN == houseBuilderSN && farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                        builder = const_cast<tagFarmer*>(&farmer);
                        break;
                    }
                }

                if (builder == nullptr && houseBuilderSN == -1) {
                    for (const auto& farmer : info.farmers) {
                        if (farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                            builder = const_cast<tagFarmer*>(&farmer);
                            houseBuilderSN = farmer.SN;
                            this->DebugText("Assigned villager #" + to_string(houseBuilderSN) + " as house builder");
                            break;
                        }
                    }
                }

                if (builder != nullptr) {
                    int ret = HumanBuild(builder->SN, BUILDING_HOME, buildX, buildY);
                    if (ret > 0) {
                        housesUnderConstruction++;
                        this->DebugText("Building house at (" + to_string(buildX) + "," + to_string(buildY) + ")");
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                occupiedPositions.insert({buildX+i, buildY+j});
                            }
                        }
                    }
                }
            } else {
                this->DebugText("Need wood for house: " + to_string(BUILD_HOUSE_WOOD) + ", have: " + to_string(info.Wood));
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::buildFishingBoatPhase(const tagInfo& info) {
    fishingBoatCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2) {
            fishingBoatCount++;
        }
    }

    this->DebugText("Fishing Boats | Current: " + to_string(fishingBoatCount) + "/" + to_string(TARGET_FISHING_BOATS));

    if (fishingBoatCount >= TARGET_FISHING_BOATS) {
        fishingBoatBuilt = true;
        currentStage = STAGE_UPGRADE_AGE;
        this->DebugText("=== Fishing boats ready, entering Age Upgrade ===");
        return;
    }

    bool productionAttemptedThisFrame = false;
    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_DOCK && building.Percent == 100) {
            int boatsProducedByThisDock = dockFishingBoatCount[building.SN];
            if (boatsProducedByThisDock < TARGET_BOATS_PER_DOCK) {
                if (building.Project == 0 && info.Wood >= BUILDING_DOCK_CREATE_SAILING_WOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_SAILING);
                    if (ret > 0) {
                        dockFishingBoatCount[building.SN]++;
                        productionAttemptedThisFrame = true;
                        return;
                    }
                }
            }
        }
    }

    if (!productionAttemptedThisFrame && fishingBoatCount < TARGET_FISHING_BOATS) {
        bool allDocksAtCapacity = true;
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_DOCK && building.Percent == 100) {
                if (dockFishingBoatCount[building.SN] < TARGET_BOATS_PER_DOCK) {
                    allDocksAtCapacity = false;
                    break;
                }
            }
        }

        if (allDocksAtCapacity && completedDocksCount < TARGET_DOCKS_NUM) {
            this->DebugText("All docks at capacity, returning to build more docks");
            currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;
            return;
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::assignFishingBoatsToFishResources(const tagInfo& info) {
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2 && farmer.NowState == HUMAN_STATE_IDLE) {
            int targetFishSN = -1;
            double minDistance = -1;

            for (const auto& resource : info.resources) {
                if (resource.Type == RESOURCE_FISH && resource.Cnt > 0) {
                    double distance = abs(farmer.BlockDR - resource.BlockDR) + abs(farmer.BlockUR - resource.BlockUR);
                    if (targetFishSN == -1 || distance < minDistance) {
                        minDistance = distance;
                        targetFishSN = resource.SN;
                    }
                }
            }

            if (targetFishSN != -1) {
                HumanAction(farmer.SN, targetFishSN);
                this->DebugText("Fishing boat #" + to_string(farmer.SN) + " -> Fish");
            } else {
                int exploreX = rand() % 128;
                int exploreY = rand() % 128;
                if (this->isOcean((*info.theMap)[exploreX][exploreY].type)) {
                    HumanMove(farmer.SN, exploreX * BLOCKSIDELENGTH, exploreY * BLOCKSIDELENGTH);
                    this->DebugText("Fishing boat #" + to_string(farmer.SN) + " exploring ocean");
                }
            }
        }
    }
}

bool UsrAI::findCoastalLandingPosition(int& x, int& y, const tagInfo& info) {
    const int searchRadius = 15;
    double minDist = 999999;
    int bestX = -1, bestY = -1;

    // 从市镇中心向外搜索
    for (int r = 1; r <= searchRadius; ++r) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                // 只检查边缘
                if (abs(i) != r && abs(j) != r) continue;

                int checkX = center_x + i;
                int checkY = center_y + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) continue;

                // 检查是否是陆地
                if (this->isMapCellLand(checkX, checkY, info)) {
                    // 检查是否靠海
                    bool isCoastal = false;
                    const int offsets[8][2] = {
                        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
                        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
                    };

                    for(const auto& offset : offsets) {
                        int adjX = checkX + offset[0];
                        int adjY = checkY + offset[1];
                        if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                            if(this->isOcean((*info.theMap)[adjX][adjY].type)) {
                                isCoastal = true;
                                break;
                            }
                        }
                    }

                    if (isCoastal) {
                        // 检查周围是否有足够的陆地空间
                        int landCount = 0;
                        for (int dx = -2; dx <= 2; dx++) {
                            for (int dy = -2; dy <= 2; dy++) {
                                int nearX = checkX + dx;
                                int nearY = checkY + dy;
                                if (nearX >= 0 && nearX < 128 && nearY >= 0 && nearY < 128) {
                                    if (this->isMapCellLand(nearX, nearY, info)) {
                                        landCount++;
                                    }
                                }
                            }
                        }

                        // 需要足够的陆地空间供村民活动
                        if (landCount >= 8) {
                            double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                            if (dist < minDist) {
                                minDist = dist;
                                bestX = checkX;
                                bestY = checkY;
                            }
                        }
                    }
                }
            }
        }
    }

    if (bestX != -1 && bestY != -1) {
        x = bestX;
        y = bestY;
        this->DebugText("Found coastal landing at (" + to_string(x) + "," + to_string(y) + ")");
        return true;
    }

    return false;
}

void UsrAI::assignTransportShipsToShore(const tagInfo& info) {
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1 && farmer.NowState == HUMAN_STATE_IDLE) {
            int landX, landY;
            if (findCoastalLandingPosition(landX, landY, info)) {
                HumanMove(farmer.SN, landX * BLOCKSIDELENGTH, landY * BLOCKSIDELENGTH);
                this->DebugText("Transport #" + to_string(farmer.SN) + " -> Shore");
            }
        }
    }
}

// Part 5: Military Phases (Warships and Army)

void UsrAI::buildWarshipsPhase(const tagInfo& info) {
    warshipCount = 0;
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            warshipCount++;
        }
    }

    this->DebugText("Warships | Current: " + to_string(warshipCount) + "/" + to_string(TARGET_WARSHIPS));

    if (warshipCount >= TARGET_WARSHIPS) {
        this->DebugText("=== Warships ready, entering Exploration ===");
        fleetsFormed = false;
        currentStage = STAGE_EXPLORE;  // Changed from STAGE_BUILD_ARMY to STAGE_EXPLORE
        return;
    }

    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_DOCK && building.Percent == 100 && building.Project == 0) {
            int warshipsProducedByThisDock = dockWarshipCount[building.SN];
            if (warshipsProducedByThisDock < TARGET_WARSHIPS_PER_DOCK) {
                if (info.Wood >= BUILDING_DOCK_CREATE_SHIP_WOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_SHIP);
                    if (ret > 0) {
                        dockWarshipCount[building.SN]++;
                        return;
                    }
                }
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::formWarshipFleets(const tagInfo& info) {
    warshipFleets.clear();
    assignedWarships.clear();
    fleetExplorationTargets.clear();
    fleetAttackTargetsSN.clear();

    std::vector<int> availableWarships;
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            availableWarships.push_back(army.SN);
        }
    }

    this->DebugText("Available warships for fleet formation: " + to_string(availableWarships.size()));

    // 改进的舰队分配：确保舰队分散
    std::sort(availableWarships.begin(), availableWarships.end());

    const int MIN_SHIPS_PER_FLEET = 2;  // 减少每个舰队的船只数量
    const int MAX_SHIPS_PER_FLEET = 3;  // 最大3艘船一个舰队

    int fleetIndex = 0;
    while (availableWarships.size() >= MIN_SHIPS_PER_FLEET) {
        std::vector<int> newFleet;
        int shipsToAssign = std::min(MAX_SHIPS_PER_FLEET, (int)availableWarships.size());

        for (int i = 0; i < shipsToAssign; ++i) {
            newFleet.push_back(availableWarships.back());
            assignedWarships.insert(availableWarships.back());
            availableWarships.pop_back();
        }

        warshipFleets.push_back(newFleet);
        this->DebugText("Fleet " + to_string(fleetIndex) + " formed with " +
                      to_string(newFleet.size()) + " ships");
        fleetIndex++;
    }

    this->DebugText("Total fleets formed: " + to_string(warshipFleets.size()));
}

void UsrAI::explorePhase(const tagInfo& info) {
    this->DebugText("=== Exploration Stage | Ships: " + to_string(warshipCount) + " ===");

    // 收集所有战船信息
    std::vector<int> allWarships;
    double fleetCenterX = 0, fleetCenterY = 0;
    int idleCount = 0;

    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            allWarships.push_back(army.SN);
            fleetCenterX += army.BlockDR;
            fleetCenterY += army.BlockUR;

            if (army.NowState == HUMAN_STATE_IDLE) {
                idleCount++;
            }
        }
    }

    if (allWarships.empty()) {
        this->DebugText("No warships available");
        return;
    }

    // 计算舰队中心
    fleetCenterX /= allWarships.size();
    fleetCenterY /= allWarships.size();

    this->DebugText("Fleet center: (" + to_string((int)fleetCenterX) + "," +
                    to_string((int)fleetCenterY) + "), Total: " +
                    to_string(allWarships.size()) + ", Idle: " + to_string(idleCount));

    // 优先级1：检查并处理敌人
    static int currentEnemyTargetSN = -1;
    static int combatCooldown = 0;  // 战斗冷却计数器

    // 清理已消失的敌方目标
    if (currentEnemyTargetSN != -1) {
        bool targetExists = false;
        for (const auto& enemy : info.enemy_armies) {
            if (enemy.SN == currentEnemyTargetSN) {
                targetExists = true;
                break;
            }
        }

        if (!targetExists) {
            this->DebugText("Enemy target eliminated");
            currentEnemyTargetSN = -1;
            combatCooldown = 20;  // 战斗结束后20帧冷却
        }
    }

    // 战斗冷却期间不要停止探索
    if (combatCooldown > 0) {
        combatCooldown--;
        this->DebugText("Combat cooldown: " + to_string(combatCooldown));
    }

    // 如果有敌方目标且没有冷却，继续攻击
    if (currentEnemyTargetSN != -1 && combatCooldown == 0) {
        this->DebugText("Continuing attack on enemy #" + to_string(currentEnemyTargetSN));

        for (int shipSN : allWarships) {
            for (const auto& army : info.armies) {
                if (army.SN == shipSN && army.NowState == HUMAN_STATE_IDLE) {
                    HumanAction(shipSN, currentEnemyTargetSN);
                    break;
                }
            }
        }
        return;
    }

    // 扫描新的敌人（只在探测范围内）
    if (currentEnemyTargetSN == -1 && combatCooldown == 0) {
        for (const auto& enemy : info.enemy_armies) {
            if (enemy.Sort == AT_SHIP) {
                double dist = sqrt(pow(fleetCenterX - enemy.BlockDR, 2) +
                                 pow(fleetCenterY - enemy.BlockUR, 2));
                if (dist <= 20) {  // 缩小攻击范围，避免追太远
                    currentEnemyTargetSN = enemy.SN;
                    this->DebugText("Enemy ship detected at distance " + to_string(dist));

                    for (int shipSN : allWarships) {
                        for (const auto& army : info.armies) {
                            if (army.SN == shipSN && army.NowState == HUMAN_STATE_IDLE) {
                                HumanAction(shipSN, currentEnemyTargetSN);
                                break;
                            }
                        }
                    }
                    return;
                }
            }
        }
    }

    // 优先级2：扫描敌方大陆
    this->scanForEnemyContinent(info);

    // 优先级3：探索逻辑优化
    static int targetX = -1;
    static int targetY = -1;
    static int stuckCounter = 0;  // 卡住计数器
    static int lastIdleCount = 0;
    static std::pair<int, int> lastFleetCenter = {-1, -1};
    static int samePositionCounter = 0;  // 相同位置计数器

    // 检测舰队是否卡住
    bool fleetStuck = false;

    // 检查舰队中心是否长时间没有移动
    if (abs(fleetCenterX - lastFleetCenter.first) < 3 &&
        abs(fleetCenterY - lastFleetCenter.second) < 3) {
        samePositionCounter++;
        if (samePositionCounter > 30) {  // 30帧位置不变
            fleetStuck = true;
            this->DebugText("Fleet stuck at same position for " +
                          to_string(samePositionCounter) + " frames");
        }
    } else {
        samePositionCounter = 0;
    }

    lastFleetCenter = {(int)fleetCenterX, (int)fleetCenterY};

    // 检查是否大部分船只空闲（可能卡住或到达目标）
    if (idleCount > allWarships.size() * 0.6) {
        stuckCounter++;
        if (stuckCounter > 10) {  // 连续10帧大部分船只空闲
            fleetStuck = true;
            this->DebugText("Most ships idle for " + to_string(stuckCounter) + " frames");
        }
    } else {
        stuckCounter = 0;
    }

    // 判断是否需要新目标
    bool needNewTarget = false;

    if (targetX == -1 || targetY == -1) {
        needNewTarget = true;
        this->DebugText("No target, need new one");
    } else if (fleetStuck) {
        needNewTarget = true;
        this->DebugText("Fleet stuck, forcing new target");
    } else {
        // 检查是否接近目标
        double distToTarget = sqrt(pow(fleetCenterX - targetX, 2) +
                                  pow(fleetCenterY - targetY, 2));
        if (distToTarget < 8) {
            needNewTarget = true;
            this->DebugText("Close to target, need new one");
        }
    }

    // 优化的探索目标选择 - 优先探索远离己方大陆的未知区域
    if (needNewTarget) {
        stuckCounter = 0;
        samePositionCounter = 0;

        // 策略1：优先探索远离己方大陆的未知区域
        int bestX = -1, bestY = -1;
        double bestScore = -1;

        // 扫描地图寻找最佳探索目标
        for (int x = 10; x < 118; x += 8) {
            for (int y = 10; y < 118; y += 8) {
                // 计算到己方大陆中心的距离
                double distFromHome = sqrt(pow(x - center_x, 2) + pow(y - center_y, 2));

                // 跳过离家太近的区域（优先探索远处）
                if (distFromHome < 35) continue;

                // 统计周围未知区域数量
                int unknownCount = 0;
                for (int dx = -15; dx <= 15; dx += 3) {
                    for (int dy = -15; dy <= 15; dy += 3) {
                        int checkX = x + dx;
                        int checkY = y + dy;
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_UNKNOWN) {
                                unknownCount++;
                            }
                        }
                    }
                }

                // 跳过已经探索过的区域
                if (unknownCount == 0) continue;

                // 检查这个位置是否可达（附近有海洋）
                bool hasOceanNearby = false;
                for (int dx = -5; dx <= 5; dx++) {
                    for (int dy = -5; dy <= 5; dy++) {
                        int checkX = x + dx;
                        int checkY = y + dy;
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                hasOceanNearby = true;
                                break;
                            }
                        }
                    }
                    if (hasOceanNearby) break;
                }

                if (!hasOceanNearby) continue;

                // 计算综合得分
                // 1. 距离己方大陆越远越好（权重最高）
                double distanceScore = distFromHome * 3.0;

                // 2. 未知区域越多越好
                double unknownScore = unknownCount * 2.0;

                // 3. 距离舰队当前位置合理（不要太远）
                double distFromFleet = sqrt(pow(x - fleetCenterX, 2) + pow(y - fleetCenterY, 2));
                double fleetDistScore = 0;
                if (distFromFleet < 30) {
                    fleetDistScore = 30;  // 近距离加分
                } else if (distFromFleet < 50) {
                    fleetDistScore = 20;  // 中距离适中
                } else {
                    fleetDistScore = 10 - (distFromFleet - 50) * 0.2;  // 太远减分
                }

                // 4. 特别优先探索地图边缘（敌方大陆可能在边缘）
                double edgeBonus = 0;
                if (x < 20 || x > 108 || y < 20 || y > 108) {
                    edgeBonus = 50;  // 边缘区域额外加分
                }

                double totalScore = distanceScore + unknownScore + fleetDistScore + edgeBonus;

                if (totalScore > bestScore) {
                    bestScore = totalScore;
                    bestX = x;
                    bestY = y;
                }
            }
        }

        if (bestX != -1 && bestY != -1) {
            targetX = bestX;
            targetY = bestY;
            double distFromHome = sqrt(pow(targetX - center_x, 2) + pow(targetY - center_y, 2));
            this->DebugText("Target: (" + to_string(targetX) + "," + to_string(targetY) +
                          ") score=" + to_string((int)bestScore) +
                          " dist_from_home=" + to_string((int)distFromHome));
        } else {
            // 策略2：向外扩展探索 - 优先远离己方大陆的方向
            static int preferredAngle = -1;
            static int spiralRadius = 50;  // 从更远的距离开始

            // 初始化：选择远离己方大陆的方向
            if (preferredAngle == -1) {
                // 根据己方大陆位置选择探索方向
                if (center_x < 64 && center_y < 64) {
                    preferredAngle = 45;  // 己方在左上，向右下探索
                } else if (center_x >= 64 && center_y < 64) {
                    preferredAngle = 135;  // 己方在右上，向左下探索
                } else if (center_x < 64 && center_y >= 64) {
                    preferredAngle = 315;  // 己方在左下，向右上探索
                } else {
                    preferredAngle = 225;  // 己方在右下，向左上探索
                }
            }

            // 在优先方向的基础上做扇形搜索
            static int angleOffset = 0;
            angleOffset += 30;
            if (angleOffset > 90) {
                angleOffset = -90;
                spiralRadius += 10;
                if (spiralRadius > 90) {
                    spiralRadius = 50;
                }
            }

            int currentAngle = preferredAngle + angleOffset;
            double radians = currentAngle * 3.14159 / 180.0;
            targetX = center_x + (int)(spiralRadius * cos(radians));
            targetY = center_y + (int)(spiralRadius * sin(radians));

            // 确保目标在地图范围内
            targetX = std::max(10, std::min(118, targetX));
            targetY = std::max(10, std::min(118, targetY));

            this->DebugText("Directed exploration: angle=" + to_string(currentAngle) +
                          " radius=" + to_string(spiralRadius) +
                          " target=(" + to_string(targetX) + "," + to_string(targetY) + ")");
        }
    }

    // 移动舰队 - 使用更紧密的编队
    this->DebugText("Moving fleet to (" + to_string(targetX) + "," + to_string(targetY) + ")");

    int movedCount = 0;
    for (size_t i = 0; i < allWarships.size(); ++i) {
        int shipSN = allWarships[i];

        const tagArmy* ship = nullptr;
        for (const auto& army : info.armies) {
            if (army.SN == shipSN) {
                ship = &army;
                break;
            }
        }

        if (!ship) continue;

        // 对空闲或移动中但可能卡住的船只发送命令
        if (ship->NowState == HUMAN_STATE_IDLE ||
            (ship->NowState == HUMAN_STATE_WALKING && fleetStuck)) {

            // 紧密编队
            int formation = i % 9;  // 3x3编队
            int row = formation / 3;
            int col = formation % 3;
            int shipTargetX = targetX + (col - 1) * 2;
            int shipTargetY = targetY + (row - 1) * 2;

            shipTargetX = std::max(5, std::min(123, shipTargetX));
            shipTargetY = std::max(5, std::min(123, shipTargetY));

            int ret = HumanMove(shipSN, shipTargetX * BLOCKSIDELENGTH, shipTargetY * BLOCKSIDELENGTH);

            if (ret > 0) {
                movedCount++;
            }
        }
    }

    this->DebugText("Moved " + to_string(movedCount) + "/" + to_string(allWarships.size()) + " ships");

    // 统计探索进度
    int unknownCount = 0;
    int totalCells = 0;
    for (int x = 0; x < 128; x += 4) {
        for (int y = 0; y < 128; y += 4) {
            totalCells++;
            if ((*info.theMap)[x][y].type == MAPPATTERN_UNKNOWN) {
                unknownCount++;
            }
        }
    }

    int exploredPercent = 100 - (unknownCount * 100 / totalCells);
    this->DebugText("Map explored: " + to_string(exploredPercent) + "%");

    // 如果发现敌方大陆且探索充分，进入下一阶段
    if (enemyContinentFound && exploredPercent > 70) {
        this->DebugText("=== Sufficient exploration (" + to_string(exploredPercent) +
                       "%), enemy continent found, entering Army Building ===");
        currentStage = STAGE_BUILD_ARMY;
        return;
    }

    // 继续其他任务
    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);

    // 提前准备运输船
    if (transportShipCount < 1) {
        this->manageTransportShipProduction(info);
    }

    // 如果发现了敌方大陆且有运输船，开始装载村民
    if (enemyContinentFound && transportShipCount > 0) {
        this->loadVillagersOntoTransports(info);
        this->commandInvasionFleet(info);
    }
}

std::pair<int, int> UsrAI::getUnifiedFleetExplorationTarget(const tagInfo& info) {
    // 获取舰队当前位置
    double fleetX = 0, fleetY = 0;
    int shipCount = 0;

    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            fleetX += army.BlockDR;
            fleetY += army.BlockUR;
            shipCount++;
        }
    }

    if (shipCount == 0) {
        return {64, 64};  // 默认中心位置
    }

    fleetX /= shipCount;
    fleetY /= shipCount;

    // 优先探索远离本土的未知区域
    std::pair<int, int> bestTarget = {-1, -1};
    double maxScore = -1;

    // 扇形搜索：从本土向外扩展
    for (int angle = 0; angle < 360; angle += 15) {  // 每15度一个扇区
        double radians = angle * 3.14159 / 180.0;

        // 从近到远搜索
        for (int radius = 30; radius <= 80; radius += 10) {
            int targetX = center_x + (int)(radius * cos(radians));
            int targetY = center_y + (int)(radius * sin(radians));

            // 确保在地图范围内
            targetX = std::max(8, std::min(120, targetX));
            targetY = std::max(8, std::min(120, targetY));

            // 检查是否是有效的海洋位置
            if (!isValidOceanPosition(targetX, targetY, info)) {
                continue;
            }

            // 计算这个位置的探索价值
            double score = 0;

            // 1. 距离本土越远越好
            double distFromHome = sqrt(pow(targetX - center_x, 2) + pow(targetY - center_y, 2));
            score += distFromHome * 2;

            // 2. 周围有未知区域加分
            int unknownCount = 0;
            for (int dx = -10; dx <= 10; dx += 5) {
                for (int dy = -10; dy <= 10; dy += 5) {
                    int checkX = targetX + dx;
                    int checkY = targetY + dy;
                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_UNKNOWN) {
                            unknownCount++;
                        }
                    }
                }
            }
            score += unknownCount * 10;

            // 3. 靠近可能的陆地边缘加分
            bool nearPossibleLand = false;
            for (int dx = -15; dx <= 15; dx += 5) {
                for (int dy = -15; dy <= 15; dy += 5) {
                    int checkX = targetX + dx;
                    int checkY = targetY + dy;
                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                            double landDist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                            if (landDist > 35) {  // 不是本土的陆地
                                nearPossibleLand = true;
                                score += 50;
                                break;
                            }
                        }
                    }
                }
                if (nearPossibleLand) break;
            }

            // 4. 距离当前位置的合理性（不要太远）
            double distFromFleet = sqrt(pow(targetX - fleetX, 2) + pow(targetY - fleetY, 2));
            if (distFromFleet > 50) {
                score -= (distFromFleet - 50);  // 太远的目标减分
            }

            // 5. 检查是否已经探索过这个扇区
            bool alreadyExplored = false;
            for (const auto& sector : exploredSectors) {
                if (abs(sector.first - targetX) < 10 && abs(sector.second - targetY) < 10) {
                    alreadyExplored = true;
                    break;
                }
            }
            if (alreadyExplored) {
                score *= 0.3;  // 已探索区域大幅减分
            }

            if (score > maxScore) {
                maxScore = score;
                bestTarget = {targetX, targetY};
            }
        }
    }

    // 如果找到了好的目标，记录这个扇区为已探索
    if (bestTarget.first != -1) {
        // 检查是否到达目标附近
        double distToTarget = sqrt(pow(fleetX - bestTarget.first, 2) +
                                  pow(fleetY - bestTarget.second, 2));
        if (distToTarget < 8) {
            exploredSectors.push_back(bestTarget);
            this->DebugText("Sector (" + to_string(bestTarget.first) + "," +
                          to_string(bestTarget.second) + ") marked as explored");
        }

        return bestTarget;
    }

    // 如果没找到好的探索目标，尝试螺旋搜索
    this->DebugText("No good exploration target found, using spiral search");

    fleetExplorationRadius += 5;
    if (fleetExplorationRadius > 70) {
        fleetExplorationRadius = 20;
    }

    double angle = (info.GameFrame % 360) * 3.14159 / 180.0;
    int spiralX = center_x + (int)(fleetExplorationRadius * cos(angle));
    int spiralY = center_y + (int)(fleetExplorationRadius * sin(angle));

    spiralX = std::max(8, std::min(120, spiralX));
    spiralY = std::max(8, std::min(120, spiralY));

    return {spiralX, spiralY};
}

void UsrAI::initializeExplorationZones(const tagInfo& info) {
    explorationZones.clear();

    // 创建更分散的探索区域
    const int ZONE_SIZE = 60;  // 减小区域大小，增加探索点密度
    const int MIN_DISTANCE_BETWEEN_ZONES = 8;  // 最小区域间距

    // 按象限分配探索区域，确保舰队分散到不同方向
    std::vector<std::pair<int, int>> quadrantCenters = {
        {32, 32},   // 左上象限
        {96, 32},   // 右上象限
        {32, 96},   // 左下象限
        {96, 96}    // 右下象限
    };

    // 为每个象限创建探索点
    for (const auto& center : quadrantCenters) {
        for (int dx = -24; dx <= 24; dx += ZONE_SIZE) {
            for (int dy = -24; dy <= 24; dy += ZONE_SIZE) {
                int x = center.first + dx;
                int y = center.second + dy;

                if (x >= 8 && x < 120 && y >= 8 && y < 120) {
                    // 检查是否与现有区域距离足够远
                    bool tooClose = false;
                    for (const auto& existing : explorationZones) {
                        int dist = abs(x - existing.first) + abs(y - existing.second);
                        if (dist < MIN_DISTANCE_BETWEEN_ZONES) {
                            tooClose = true;
                            break;
                        }
                    }

                    if (!tooClose && isValidOceanPosition(x, y, info)) {
                        explorationZones.push_back({x, y});
                    }
                }
            }
        }
    }

    // 添加边缘探索点
    for (int i = 16; i < 112; i += 16) {
        if (isValidOceanPosition(i, 16, info)) explorationZones.push_back({i, 16});  // 上边缘
        if (isValidOceanPosition(i, 112, info)) explorationZones.push_back({i, 112}); // 下边缘
        if (isValidOceanPosition(16, i, info)) explorationZones.push_back({16, i});   // 左边缘
        if (isValidOceanPosition(112, i, info)) explorationZones.push_back({112, i}); // 右边缘
    }

    explorationZonesInitialized = true;
    this->DebugText("Initialized " + to_string(explorationZones.size()) + " exploration zones");
}

bool UsrAI::findValidExplorationTarget(int fleetIndex, int& targetX, int& targetY, const tagInfo& info) {
    const tagArmy* fleetLeader = nullptr;
    if (!warshipFleets[fleetIndex].empty()) {
        int leaderSN = warshipFleets[fleetIndex][0];
        for (const auto& army : info.armies) {
            if (army.SN == leaderSN) {
                fleetLeader = &army;
                break;
            }
        }
    }

    if (!fleetLeader) return false;

    // 为每个舰队分配不同象限的探索区域
    int quadrant = fleetIndex % 4;  // 0=左上, 1=右上, 2=左下, 3=右下

    std::vector<std::vector<int>> quadrantBounds = {
        {8, 64, 8, 64},     // 左上象限
        {64, 120, 8, 64},   // 右上象限
        {8, 64, 64, 120},   // 左下象限
        {64, 120, 64, 120}  // 右下象限
    };

    auto bounds = quadrantBounds[quadrant];
    int minX = bounds[0], maxX = bounds[1];
    int minY = bounds[2], maxY = bounds[3];

    // 优先寻找指定象限内的未知区域
    double minDist = 1e9;
    bool foundTarget = false;

    // 扩大搜索步长，提高效率
    for (int x = minX; x < maxX; x += 4) {
        for (int y = minY; y < maxY; y += 4) {
            if ((*info.theMap)[x][y].type == MAPPATTERN_UNKNOWN) {
                // 检查这个位置是否太接近其他舰队的目标
                bool tooClose = false;
                for (const auto& otherTarget : fleetExplorationTargets) {
                    if (otherTarget.first != fleetIndex) {
                        double dist = sqrt(pow(x - otherTarget.second.first, 2) +
                                         pow(y - otherTarget.second.second, 2));
                        if (dist < 15) {  // 舰队间最小距离
                            tooClose = true;
                            break;
                        }
                    }
                }

                if (!tooClose) {
                    double dist = sqrt(pow(x - fleetLeader->BlockDR, 2) +
                                     pow(y - fleetLeader->BlockUR, 2));
                    if (dist < minDist) {
                        minDist = dist;
                        targetX = x;
                        targetY = y;
                        foundTarget = true;
                    }
                }
            }
        }
    }

    // 如果在指定象限没找到，扩展到全地图搜索，但使用更大的步长
    if (!foundTarget) {
        for (int x = 8; x < 120; x += 6) {
            for (int y = 8; y < 120; y += 6) {
                if ((*info.theMap)[x][y].type == MAPPATTERN_UNKNOWN) {
                    bool tooClose = false;
                    for (const auto& otherTarget : fleetExplorationTargets) {
                        if (otherTarget.first != fleetIndex) {
                            double dist = sqrt(pow(x - otherTarget.second.first, 2) +
                                             pow(y - otherTarget.second.second, 2));
                            if (dist < 12) {
                                tooClose = true;
                                break;
                            }
                        }
                    }

                    if (!tooClose) {
                        double dist = sqrt(pow(x - fleetLeader->BlockDR, 2) +
                                         pow(y - fleetLeader->BlockUR, 2));
                        if (dist < minDist) {
                            minDist = dist;
                            targetX = x;
                            targetY = y;
                            foundTarget = true;
                        }
                    }
                }
            }
        }
    }

    // 如果还是没找到，寻找最远的已探索但可能有价值的区域
    if (!foundTarget) {
        for (int x = 16; x < 112; x += 8) {
            for (int y = 16; y < 112; y += 8) {
                if ((*info.theMap)[x][y].type == MAPPATTERN_OCEAN) {
                    // 检查周围是否有未探索区域
                    bool nearUnknown = false;
                    for (int dx = -8; dx <= 8; dx += 4) {
                        for (int dy = -8; dy <= 8; dy += 4) {
                            int checkX = x + dx;
                            int checkY = y + dy;
                            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_UNKNOWN) {
                                    nearUnknown = true;
                                    break;
                                }
                            }
                        }
                        if (nearUnknown) break;
                    }

                    if (nearUnknown) {
                        bool tooClose = false;
                        for (const auto& otherTarget : fleetExplorationTargets) {
                            if (otherTarget.first != fleetIndex) {
                                double dist = sqrt(pow(x - otherTarget.second.first, 2) +
                                                 pow(y - otherTarget.second.second, 2));
                                if (dist < 10) {
                                    tooClose = true;
                                    break;
                                }
                            }
                        }

                        if (!tooClose) {
                            double dist = sqrt(pow(x - fleetLeader->BlockDR, 2) +
                                             pow(y - fleetLeader->BlockUR, 2));
                            if (dist < minDist) {
                                minDist = dist;
                                targetX = x;
                                targetY = y;
                                foundTarget = true;
                            }
                        }
                    }
                }
            }
        }
    }

    if (foundTarget) {
        this->DebugText("Fleet " + to_string(fleetIndex) + " found exploration target at (" +
                      to_string(targetX) + "," + to_string(targetY) + ") in quadrant " +
                      to_string(quadrant) + " (distance: " + to_string(minDist) + ")");
    } else {
        this->DebugText("Fleet " + to_string(fleetIndex) + " could not find exploration target in quadrant " + to_string(quadrant));
    }

    return foundTarget;
}

// 获取巡逻目标
std::pair<int, int> UsrAI::getPatrolTarget(int fleetIndex, const tagInfo& info) {
    // 检查当前巡逻目标是否需要更新
    bool needNewTarget = true;

    if (fleetPatrolTargets.count(fleetIndex)) {
        auto currentTarget = fleetPatrolTargets[fleetIndex];

        // 检查舰队领导者位置
        if (!warshipFleets[fleetIndex].empty()) {
            int leaderSN = warshipFleets[fleetIndex][0];
            for (const auto& army : info.armies) {
                if (army.SN == leaderSN) {
                    double dist = sqrt(pow(army.BlockDR - currentTarget.first, 2) +
                                     pow(army.BlockUR - currentTarget.second, 2));
                    if (dist > 5) {  // 放宽到达判定距离
                        needNewTarget = false;  // 继续前往当前目标
                    }
                    break;
                }
            }
        }
    }

    if (!needNewTarget) {
        return fleetPatrolTargets[fleetIndex];
    }

    // 为不同舰队分配不同的巡逻模式
    int patrolPattern = fleetIndex % 4;  // 4种不同的巡逻模式
    int timeOffset = (info.GameFrame / 200 + fleetIndex * 3) % 16;  // 更多巡逻点

    std::pair<int, int> newTarget;

    switch (patrolPattern) {
        case 0: // 水平巡逻
            {
                std::vector<std::pair<int, int>> horizontalPath = {
                    {20 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {40 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {60 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {80 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 25 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 45 + fleetIndex * 8},
                    {80 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {60 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {40 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {20 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {20 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {40 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {60 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {80 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 65 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 85 + fleetIndex * 8}
                };
                newTarget = horizontalPath[timeOffset % horizontalPath.size()];
            }
            break;

        case 1: // 垂直巡逻
            {
                std::vector<std::pair<int, int>> verticalPath = {
                    {25 + fleetIndex * 12, 20},
                    {25 + fleetIndex * 12, 35},
                    {25 + fleetIndex * 12, 50},
                    {25 + fleetIndex * 12, 65},
                    {25 + fleetIndex * 12, 80},
                    {25 + fleetIndex * 12, 95},
                    {45 + fleetIndex * 12, 95},
                    {45 + fleetIndex * 12, 80},
                    {45 + fleetIndex * 12, 65},
                    {45 + fleetIndex * 12, 50},
                    {45 + fleetIndex * 12, 35},
                    {45 + fleetIndex * 12, 20},
                    {65 + fleetIndex * 12, 20},
                    {65 + fleetIndex * 12, 35},
                    {65 + fleetIndex * 12, 50},
                    {65 + fleetIndex * 12, 65}
                };
                newTarget = verticalPath[timeOffset % verticalPath.size()];
            }
            break;

        case 2: // 对角线巡逻
            {
                if ((timeOffset % 8) < 4) {
                    int step = timeOffset % 4;
                    newTarget = {25 + step * 20 + fleetIndex * 4, 25 + step * 20 + fleetIndex * 4};
                } else {
                    int step = (timeOffset % 4);
                    newTarget = {105 - step * 20 - fleetIndex * 4, 25 + step * 20 + fleetIndex * 4};
                }
            }
            break;

        case 3: // 圆形巡逻
            {
                double angle = (timeOffset * 22.5 + fleetIndex * 30.0) * 3.14159 / 180.0;
                int radius = 20 + fleetIndex * 6;
                int centerX = 64 + (fleetIndex % 2 == 0 ? -15 : 15);
                int centerY = 64 + (fleetIndex < 2 ? -15 : 15);
                newTarget = {
                    centerX + (int)(radius * cos(angle)),
                    centerY + (int)(radius * sin(angle))
                };
            }
            break;
    }

    // 确保目标在有效海洋范围内
    newTarget.first = std::max(16, std::min(112, newTarget.first));
    newTarget.second = std::max(16, std::min(112, newTarget.second));

    // 验证目标是否是有效的海洋位置
    int retryCount = 0;
    while (!isValidOceanPosition(newTarget.first, newTarget.second, info) && retryCount < 5) {
        // 如果不是海洋，尝试附近的位置
        newTarget.first += (rand() % 11 - 5);
        newTarget.second += (rand() % 11 - 5);
        newTarget.first = std::max(16, std::min(112, newTarget.first));
        newTarget.second = std::max(16, std::min(112, newTarget.second));
        retryCount++;
    }

    // 如果还是找不到有效位置，使用默认安全位置
    if (!isValidOceanPosition(newTarget.first, newTarget.second, info)) {
        newTarget = {32 + fleetIndex * 16, 32 + fleetIndex * 16};
    }

    fleetPatrolTargets[fleetIndex] = newTarget;
    this->DebugText("Fleet " + to_string(fleetIndex) + " new patrol target: (" +
                  to_string(newTarget.first) + "," + to_string(newTarget.second) +
                  ") pattern " + to_string(patrolPattern));

    return newTarget;
}

bool UsrAI::isValidOceanPosition(int x, int y, const tagInfo& info) {
    if (x < 0 || y < 0 || x >= 128 || y >= 128) {
        return false;
    }
    return (*info.theMap)[x][y].type == MAPPATTERN_OCEAN;
}

bool UsrAI::isPositionNearMapEdge(int x, int y) {
    const int EDGE_THRESHOLD = 5;
    return (x < EDGE_THRESHOLD || y < EDGE_THRESHOLD ||
            x >= (128 - EDGE_THRESHOLD) || y >= (128 - EDGE_THRESHOLD));
}

// 村民上运输船逻辑
void UsrAI::loadVillagersOntoTransports(const tagInfo& info) {
    // 统计已运输的村民
    villagersTransported = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {  // 陆地村民
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 40) {  // 在敌方大陆上
                villagersTransported++;
            }
        }
    }

    this->DebugText("=== Transport Loading Phase ===");
    this->DebugText("Villagers already transported: " + to_string(villagersTransported));

    // 如果已经运输了足够的村民，返回
    if (villagersTransported >= 5) {
        this->DebugText("Already transported enough villagers");
        return;
    }

    // 只有发现敌方大陆后才开始装载村民
    if (!enemyContinentFound) {
        this->DebugText("Enemy continent not yet found, waiting...");
        return;
    }

    // 查找运输船
    tagFarmer* transport = nullptr;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) {  // 运输船
            transport = const_cast<tagFarmer*>(&farmer);
            break;
        }
    }

    if (!transport) {
        this->DebugText("No transport ship found!");
        return;
    }

    // 输出运输船状态
    this->DebugText("Transport #" + to_string(transport->SN) +
                  " at (" + to_string(transport->BlockDR) + "," + to_string(transport->BlockUR) +
                  ") state=" + to_string(transport->NowState) +
                  " villagers=" + to_string(transport->Resource));

    int distFromCenter = abs(transport->BlockDR - center_x) + abs(transport->BlockUR - center_y);

    // 静态变量记录等待状态
    static int transportWaitingFrames = 0;
    static int lastTransportResource = 0;
    static bool transportDeparted = false;  // 记录运输船是否已经出发

    // 检测是否有新村民上船
    if (transport->Resource > lastTransportResource) {
        transportWaitingFrames = 0;  // 有新村民上船，重置等待计数
        transportDeparted = false;   // 重置出发状态
        this->DebugText("New villager boarded, reset waiting timer");
    }
    lastTransportResource = transport->Resource;

    // 根据运输船状态执行不同操作

    // 情况0：运输船正在移动中（WALKING状态）
    if (transport->NowState == HUMAN_STATE_WALKING) {
        // 检查是否在前往敌方大陆
        int targetX = (int)(transport->DR0 / BLOCKSIDELENGTH);
        int targetY = (int)(transport->UR0 / BLOCKSIDELENGTH);

        if (abs(targetX - selectedLandingX) < 5 && abs(targetY - selectedLandingY) < 5) {
            this->DebugText("Transport is sailing to enemy continent (" +
                          to_string(targetX) + "," + to_string(targetY) + ")");
            transportDeparted = true;
            return;  // 运输船正在前往敌方大陆，不需要其他操作
        } else {
            this->DebugText("Transport is moving to (" + to_string(targetX) + "," +
                          to_string(targetY) + ")");
            return;  // 运输船正在移动，等待它完成
        }
    }

    // 情况1：船上有村民且已经出发
    if (transportDeparted && transport->Resource > 0) {
        this->DebugText("Transport already departed with " + to_string(transport->Resource) + " villagers");
        return;
    }

    // ==================== MODIFICATION START ====================
    // 情况2：船上有村民，决定是否出发
    if (transport->Resource > 0 && !transportDeparted) {
        bool shouldDepart = false;

        // 判断出发条件：只要满5个人就出发
        if (transport->Resource >= 5) {
            shouldDepart = true;
            this->DebugText("Transport full (5/5), departing to enemy continent.");
        }

        // 执行出发命令
        if (shouldDepart && transport->NowState == HUMAN_STATE_IDLE) {
            if (selectedLandingX != -1 && selectedLandingY != -1) {
                int ret = HumanMove(transport->SN,
                                  selectedLandingX * BLOCKSIDELENGTH,
                                  selectedLandingY * BLOCKSIDELENGTH);
                this->DebugText("DEPARTING: Transport with " + to_string(transport->Resource) +
                              " units to (" + to_string(selectedLandingX) + "," +
                              to_string(selectedLandingY) + "), ret=" + to_string(ret));

                if (ret > 0) {
                    transportDeparted = true;
                    transportWaitingFrames = 0;
                }
                return;
            } else {
                 this->DebugText("Cannot depart: No landing position selected.");
            }
        }
    }
    // ===================== MODIFICATION END =====================

    // 情况3：运输船空载且太远，召回
    if (distFromCenter > 35 && transport->Resource == 0 && transport->NowState == HUMAN_STATE_IDLE) {
        this->DebugText("Empty transport too far, recalling...");

        // 移动到本土市镇中心附近的海域
        int targetX = -1, targetY = -1;
        double minDist = 999999;

        for (int dx = -10; dx <= 10; dx++) {
            for (int dy = -10; dy <= 10; dy++) {
                int checkX = center_x + dx;
                int checkY = center_y + dy;

                if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                    if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                        // 检查是否靠近陆地
                        bool nearLand = false;
                        for (int ddx = -1; ddx <= 1; ddx++) {
                            for (int ddy = -1; ddy <= 1; ddy++) {
                                int landX = checkX + ddx;
                                int landY = checkY + ddy;
                                if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                                    if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                        nearLand = true;
                                        break;
                                    }
                                }
                            }
                            if (nearLand) break;
                        }

                        if (nearLand) {
                            double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                            if (dist < minDist) {
                                minDist = dist;
                                targetX = checkX;
                                targetY = checkY;
                            }
                        }
                    }
                }
            }
        }

        if (targetX != -1 && targetY != -1) {
            int ret = HumanMove(transport->SN, targetX * BLOCKSIDELENGTH, targetY * BLOCKSIDELENGTH);
            this->DebugText("Recalling to home waters at (" + to_string(targetX) + "," +
                          to_string(targetY) + "), ret=" + to_string(ret));
            transportDeparted = false;
            transportWaitingFrames = 0;
        }
        return;
    }

    // 情况4：运输船在本土附近，准备装载村民
    if (distFromCenter <= 35 && transport->Resource < 5 && transport->NowState == HUMAN_STATE_IDLE) {
        // 检查运输船是否在合适的位置（靠近陆地的海域）
        bool nearLand = false;
        for (int dx = -2; dx <= 2; dx++) {
            for (int dy = -2; dy <= 2; dy++) {
                int checkX = transport->BlockDR + dx;
                int checkY = transport->BlockUR + dy;
                if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                    if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                        nearLand = true;
                        break;
                    }
                }
                if (nearLand) break;
            }
        }

        if (!nearLand) {
            // 运输船需要移动到靠近陆地的海洋位置
            this->DebugText("Transport not near land, moving closer...");

            // 寻找最近的靠岸海洋位置
            int targetX = -1, targetY = -1;
            double minDist = 999999;

            for (int x = center_x - 15; x <= center_x + 15; x++) {
                for (int y = center_y - 15; y <= center_y + 15; y++) {
                    if (x >= 0 && x < 128 && y >= 0 && y < 128) {
                        if ((*info.theMap)[x][y].type == MAPPATTERN_OCEAN) {
                            // 检查是否紧邻陆地
                            bool adjacentToLand = false;
                            for (int dx = -1; dx <= 1; dx++) {
                                for (int dy = -1; dy <= 1; dy++) {
                                    if (dx == 0 && dy == 0) continue;
                                    int landX = x + dx;
                                    int landY = y + dy;
                                    if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                                        if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                            adjacentToLand = true;
                                            break;
                                        }
                                    }
                                }
                                if (adjacentToLand) break;
                            }

                            if (adjacentToLand) {
                                double dist = sqrt(pow(x - transport->BlockDR, 2) +
                                                 pow(y - transport->BlockUR, 2));
                                if (dist < minDist) {
                                    minDist = dist;
                                    targetX = x;
                                    targetY = y;
                                }
                            }
                        }
                    }
                }
            }

            if (targetX != -1 && targetY != -1) {
                int ret = HumanMove(transport->SN, targetX * BLOCKSIDELENGTH, targetY * BLOCKSIDELENGTH);
                this->DebugText("Moving to loading position (" + to_string(targetX) +
                              "," + to_string(targetY) + "), ret=" + to_string(ret));
                return;
            }
        }

        // 运输船已在合适位置，开始装载村民
        if (nearLand) {
            this->DebugText("Transport in loading position, finding villagers...");

            int villagersNeeded = 5 - transport->Resource;
            std::vector<std::pair<int, double>> availableVillagers;

            // 找出所有可用的村民
            for (const auto& villager : info.farmers) {
                if (villager.FarmerSort == 0) {  // 陆地村民
                    // 计算村民到运输船的距离
                    double dist = sqrt(pow(villager.BlockDR - transport->BlockDR, 2) +
                                     pow(villager.BlockUR - transport->BlockUR, 2));

                    // 只考虑较近的村民（距离小于25）
                    if (dist < 25) {
                        // 优先使用空闲村民
                        if (villager.NowState == HUMAN_STATE_IDLE) {
                            availableVillagers.push_back(std::make_pair(villager.SN, dist));
                        }
                        // 如果空闲村民不够，可以征用工作中的村民
                        else if (villager.NowState == HUMAN_STATE_WORKING &&
                                (int)availableVillagers.size() < villagersNeeded) {
                            // 检查是否在做关键工作
                            bool criticalWork = false;
                            if (info.Wood < 100 || info.Meat < 100) {
                                criticalWork = true;  // 资源紧缺时不征用
                            }

                            if (!criticalWork) {
                                availableVillagers.push_back(std::make_pair(villager.SN, dist + 100)); // 距离加权
                            }
                        }
                    }
                }
            }

            // 按距离排序
            std::sort(availableVillagers.begin(), availableVillagers.end(),
                     [](const std::pair<int, double>& a, const std::pair<int, double>& b) {
                         return a.second < b.second;
                     });

            this->DebugText("Found " + to_string(availableVillagers.size()) +
                          " available villagers, need " + to_string(villagersNeeded));

            // 让村民上船
            int boardingCommands = 0;
            for (size_t i = 0; i < availableVillagers.size() && boardingCommands < villagersNeeded; i++) {
                int villagerSN = availableVillagers[i].first;

                // 先检查村民是否还存在
                bool villagerExists = false;
                for (const auto& v : info.farmers) {
                    if (v.SN == villagerSN && v.FarmerSort == 0) {
                        // 如果村民在工作，先停止工作
                        if (v.NowState == HUMAN_STATE_WORKING) {
                            // 移动到当前位置（停止工作）
                            HumanMove(villagerSN, v.DR, v.UR);
                            this->DebugText("Stopping work for villager #" + to_string(villagerSN));
                        }
                        villagerExists = true;
                        break;
                    }
                }

                if (villagerExists) {
                    // 命令村民上船
                    int ret = HumanAction(villagerSN, transport->SN);
                    if (ret > 0) {
                        boardingCommands++;
                        this->DebugText("Villager #" + to_string(villagerSN) +
                                      " ordered to board transport");
                    }
                }
            }

            if (boardingCommands > 0) {
                this->DebugText("Issued " + to_string(boardingCommands) + " boarding commands");
            }
        }
    }
}

void UsrAI::landInvasionPhase(const tagInfo& info) {
    this->DebugText("=== Land Invasion Phase ===");

    // 扫描敌方大陆
    if (!enemyContinentFound) {
        this->scanForEnemyContinent(info);
        if (!enemyContinentFound) {
            this->DebugText("Enemy continent not found, exploring");
            this->explorePhase(info);
            return;
        }
    }

    // 确保有一艘运输船
    transportShipCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) {  // 运输船
            transportShipCount++;
        }
    }

    if (transportShipCount < 1) {
        this->DebugText("Building transport ship for invasion");
        this->manageTransportShipProduction(info);
        // 继续本土的资源采集
        this->assignTasksToVillagersWithLimits(info, false);
        this->assignFishingBoatsToFishResources(info);
        return;
    }

    // 统计已运输的村民数量
    villagersTransported = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {  // 陆地村民
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 40) {  // 在敌方大陆上
                villagersTransported++;
            }
        }
    }

    this->DebugText("Transport ships: " + to_string(transportShipCount) +
                    ", Villagers on enemy continent: " + to_string(villagersTransported) + "/5");

    // 装载村民（每帧都尝试）
    if (villagersTransported < 5 && transportShipCount > 0) {
        this->loadVillagersOntoTransports(info);
    }

    // 装载军队上船
    this->loadArmyOntoTransports(info);

    // 指挥入侵舰队（包括运输船）
    this->commandInvasionFleet(info);

    // 管理战斗
    this->manageCombat(info);

    // 扫描金矿
    this->scanForGold(info);

    // 检查金矿区域是否安全
    bool areaSecured = true;
    int enemiesNearGold = 0;

    if (!goldPositions.empty()) {
        for (const auto& enemy : info.enemy_armies) {
            for (const auto& goldPos : goldPositions) {
                int dist = abs(enemy.BlockDR - goldPos.first) + abs(enemy.BlockUR - goldPos.second);
                if (dist < 15) {
                    areaSecured = false;
                    enemiesNearGold++;
                }
            }
        }

        for (const auto& enemy : info.enemy_buildings) {
            if (enemy.Type == BUILDING_ARROWTOWER) {
                for (const auto& goldPos : goldPositions) {
                    int dist = abs(enemy.BlockDR - goldPos.first) + abs(enemy.BlockUR - goldPos.second);
                    if (dist < 10) {
                        areaSecured = false;
                        enemiesNearGold++;
                    }
                }
            }
        }
    }

    if (enemiesNearGold > 0) {
        this->DebugText("Enemies near gold: " + to_string(enemiesNearGold));
    }

    // 如果区域安全且发现了金矿，进入收集金矿阶段
    if (areaSecured && goldFound && villagersTransported >= 3) {
        this->DebugText("=== Area secured with " + to_string(villagersTransported) +
                       " villagers, entering gold collection ===");
        currentStage = STAGE_COLLECT_GOLD;
    }

    // 继续本土的资源采集
    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);

    // 持续生产军队支援
    if (armyCampBuilt) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_ARMYCAMP && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_ARMYCAMP_CREATE_CLUBMAN_FOOD) {
                    BuildingAction(building.SN, BUILDING_ARMYCAMP_CREATE_CLUBMAN);
                    break;
                }
            }
        }
    }
}

void UsrAI::scanForGold(const tagInfo& info) {
    if (goldFound) return;

    goldPositions.clear();

    for (const auto& res : info.resources) {
        if (res.Type == RESOURCE_GOLD) {
            goldPositions.push_back(std::make_pair(res.BlockDR, res.BlockUR));

            if (!goldFound) {
                goldFound = true;
                this->DebugText("Gold found at (" + to_string(res.BlockDR) +
                              "," + to_string(res.BlockUR) + ")");
            }
        }
    }

    if (goldFound) {
        this->DebugText("Total gold deposits found: " + to_string(goldPositions.size()));
    }
}


// Fixed buildArmyPhase with proper villager assignment
void UsrAI::buildArmyPhase(const tagInfo& info) {
    this->DebugText("=== Army Building ===");

    clubmanCount = 0;
    slingerCount = 0;
    bowmanCount = 0;
    scoutCount = 0;
    landArmy.clear();

    for (const auto& army : info.armies) {
        switch(army.Sort) {
            case AT_CLUBMAN:
            case AT_SWORDSMAN:
                clubmanCount++;
                landArmy.push_back(army.SN);
                break;
            case AT_SLINGER:
                slingerCount++;
                landArmy.push_back(army.SN);
                break;
            case AT_BOWMAN:
                bowmanCount++;
                landArmy.push_back(army.SN);
                break;
            case AT_SCOUT:
                scoutCount++;
                landArmy.push_back(army.SN);
                break;
        }
    }

    this->DebugText("Army: Club=" + to_string(clubmanCount) + "/" + to_string(TARGET_CLUBMAN) +
                    " Sling=" + to_string(slingerCount) + "/" + to_string(TARGET_SLINGER) +
                    " Bow=" + to_string(bowmanCount) + "/" + to_string(TARGET_BOWMAN) +
                    " Scout=" + to_string(scoutCount) + "/" + to_string(TARGET_SCOUT));

    if (clubmanCount >= TARGET_CLUBMAN &&
        slingerCount >= TARGET_SLINGER &&
        bowmanCount >= TARGET_BOWMAN &&
        scoutCount >= TARGET_SCOUT) {
        this->DebugText("=== Army ready, entering Invasion ===");
        currentStage = STAGE_LAND_INVASION;
        return;
    }

    armyCampBuilt = false;
    rangeBuilt = false;
    stableBuilt = false;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_ARMYCAMP && b.Percent == 100) armyCampBuilt = true;
        if (b.Type == BUILDING_RANGE && b.Percent == 100) rangeBuilt = true;
        if (b.Type == BUILDING_STABLE && b.Percent == 100) stableBuilt = true;
    }

    bool buildingInProgress = false;
    for (const auto& b : info.buildings) {
        if ((b.Type == BUILDING_ARMYCAMP || b.Type == BUILDING_RANGE || b.Type == BUILDING_STABLE) &&
            b.Percent < 100) {
            buildingInProgress = true;
            break;
        }
    }

    if (!armyCampBuilt && !buildingInProgress) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_ARMYCAMP)) {
            if (info.Wood >= BUILD_ARMYCAMP_WOOD) {
                for (const auto& farmer : info.farmers) {
                    if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        int ret = HumanBuild(farmer.SN, BUILDING_ARMYCAMP, buildX, buildY);
                        if (ret > 0) {
                            for (int i = 0; i < 3; i++) {
                                for (int j = 0; j < 3; j++) {
                                    occupiedPositions.insert({buildX+i, buildY+j});
                                }
                            }
                            buildingInProgress = true;
                        }
                        break;
                    }
                }
            }
        }
    }

    if (!rangeBuilt && !buildingInProgress && armyCampBuilt) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_RANGE)) {
            if (info.Wood >= BUILD_RANGE_WOOD) {
                for (const auto& farmer : info.farmers) {
                    if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        int ret = HumanBuild(farmer.SN, BUILDING_RANGE, buildX, buildY);
                        if (ret > 0) {
                            for (int i = 0; i < 3; i++) {
                                for (int j = 0; j < 3; j++) {
                                    occupiedPositions.insert({buildX+i, buildY+j});
                                }
                            }
                            buildingInProgress = true;
                        }
                        break;
                    }
                }
            }
        }
    }

    if (!stableBuilt && !buildingInProgress && armyCampBuilt) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_STABLE)) {
            if (info.Wood >= BUILD_STABLE_WOOD) {
                for (const auto& farmer : info.farmers) {
                    if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        int ret = HumanBuild(farmer.SN, BUILDING_STABLE, buildX, buildY);
                        if (ret > 0) {
                            for (int i = 0; i < 3; i++) {
                                for (int j = 0; j < 3; j++) {
                                    occupiedPositions.insert({buildX+i, buildY+j});
                                }
                            }
                            buildingInProgress = true;
                        }
                        break;
                    }
                }
            }
        }
    }

    if (!toolUseUpgraded) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_STOCK && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_STOCK_UPGRADE_USETOOL_FOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_STOCK_UPGRADE_USETOOL);
                    if (ret > 0) {
                        toolUseUpgraded = true;
                    }
                    break;
                }
            }
        }
    }

    this->manageArmyProduction(info);

    // IMPORTANT: Keep villagers working during army building
    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::manageArmyProduction(const tagInfo& info) {
    if (clubmanCount < TARGET_CLUBMAN) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_ARMYCAMP && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_ARMYCAMP_CREATE_CLUBMAN_FOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_ARMYCAMP_CREATE_CLUBMAN);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }

    if (slingerCount < TARGET_SLINGER) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_ARMYCAMP && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_ARMYCAMP_CREATE_SLINGER_FOOD &&
                    info.Stone >= BUILDING_ARMYCAMP_CREATE_SLINGER_STONE) {
                    int ret = BuildingAction(building.SN, BUILDING_ARMYCAMP_CREATE_SLINGER);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }

    if (bowmanCount < TARGET_BOWMAN) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_RANGE && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_RANGE_CREATE_BOWMAN_FOOD &&
                    info.Wood >= BUILDING_RANGE_CREATE_BOWMAN_WOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_RANGE_CREATE_BOWMAN);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }

    if (scoutCount < TARGET_SCOUT) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_STABLE && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_STABLE_CREATE_SCOUT_FOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_STABLE_CREATE_SCOUT);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }
}

void UsrAI::manageTransportShipProduction(const tagInfo& info) {
    // 只生产一艘运输船
    if (transportShipCount >= 1) {
        this->DebugText("Transport ship already built");
        return;
    }

    // 寻找可用的船坞来生产运输船
    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_DOCK && building.Percent == 100 && building.Project == 0) {
            // 检查是否有足够的木材
            if (info.Wood >= BUILDING_DOCK_CREATE_WOOD_BOAT_WOOD) {
                int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_WOOD_BOAT);
                if (ret > 0) {
                    dockTransportShipCount[building.SN]++;
                    this->DebugText("Building transport ship at dock #" + to_string(building.SN));
                    return;  // 只需要一艘，生产后立即返回
                }
            } else {
                this->DebugText("Need " + to_string(BUILDING_DOCK_CREATE_WOOD_BOAT_WOOD) +
                              " wood for transport ship, have " + to_string(info.Wood));
            }
        }
    }
}
// Part 6: Invasion and Gold Collection

void UsrAI::scanForEnemyContinent(const tagInfo& info) {
    if (enemyContinentFound) return;

    enemyLandPositions.clear();
    landingPositions.clear();

    for (int x = 0; x < 128; x++) {
        for (int y = 0; y < 128; y++) {
            if ((*info.theMap)[x][y].type == MAPPATTERN_GRASS) {
                int dist = abs(x - center_x) + abs(y - center_y);
                if (dist > 40) {  // 远离本土的陆地
                    enemyLandPositions.push_back(std::make_pair(x, y));

                    if (!enemyContinentFound) {
                        enemyContinentX = x;
                        enemyContinentY = y;
                        enemyContinentFound = true;
                        this->DebugText("Enemy continent found at (" + to_string(x) + "," + to_string(y) + ")");
                    }

                    // 检查是否是靠海的陆地（可以作为登陆点）
                    bool isCoastal = false;
                    const int offsets[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
                    for (const auto& offset : offsets) {
                        int checkX = x + offset[0];
                        int checkY = y + offset[1];
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                isCoastal = true;
                                break;
                            }
                        }
                    }

                    if (isCoastal) {
                        // 确保周围有足够的陆地空间供村民活动
                        int landCount = 0;
                        for (int dx = -2; dx <= 2; dx++) {
                            for (int dy = -2; dy <= 2; dy++) {
                                int nearX = x + dx;
                                int nearY = y + dy;
                                if (nearX >= 0 && nearX < 128 && nearY >= 0 && nearY < 128) {
                                    if ((*info.theMap)[nearX][nearY].type == MAPPATTERN_GRASS) {
                                        landCount++;
                                    }
                                }
                            }
                        }

                        // 需要足够的陆地空间（至少10个格子）
                        if (landCount >= 10) {
                            landingPositions.push_back(std::make_pair(x, y));
                        }
                    }
                }
            }
        }
    }

    // 选择最佳登陆点
    if (!landingPositions.empty()) {
        int bestX = -1, bestY = -1;
        double bestScore = -999999;

        for (const auto& pos : landingPositions) {
            double score = 0;

            // 距离本土越远越好
            double distFromHome = sqrt(pow(pos.first - center_x, 2) + pow(pos.second - center_y, 2));
            score += distFromHome;

            // 检查附近敌军数量（越少越好）
            for (const auto& enemy : info.enemy_armies) {
                double dist = sqrt(pow(pos.first - enemy.BlockDR, 2) + pow(pos.second - enemy.BlockUR, 2));
                if (dist < 15) {
                    score -= 20;
                }
            }

            // 检查附近敌方建筑
            for (const auto& enemy : info.enemy_buildings) {
                double dist = sqrt(pow(pos.first - enemy.BlockDR, 2) + pow(pos.second - enemy.BlockUR, 2));
                if (dist < 10) {
                    score -= 30;
                }
            }

            if (score > bestScore) {
                bestScore = score;
                bestX = pos.first;
                bestY = pos.second;
            }
        }

        if (bestX != -1) {
            selectedLandingX = bestX;
            selectedLandingY = bestY;
            this->DebugText("Selected landing position: (" + to_string(selectedLandingX) +
                          "," + to_string(selectedLandingY) + ") - coastal land tile, score=" +
                          to_string((int)bestScore));
        }
    } else {
        this->DebugText("No suitable landing positions found!");
    }
}

void UsrAI::loadArmyOntoTransports(const tagInfo& info) {
    std::vector<int> idleTransports;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1 && farmer.NowState == HUMAN_STATE_IDLE && farmer.Resource < 5) {
            idleTransports.push_back(farmer.SN);
        }
    }

    if (idleTransports.empty()) return;

    for (const auto& army : info.armies) {
        if (boardedUnits.count(army.SN)) continue;

        if (army.Sort != AT_SHIP) {
            for (int transportSN : idleTransports) {
                int ret = HumanAction(army.SN, transportSN);
                if (ret > 0) {
                    boardedUnits.insert(army.SN);
                    this->DebugText("Army #" + to_string(army.SN) + " boarded transport #" + to_string(transportSN));
                    break;
                }
            }
        }
    }
}

void UsrAI::commandInvasionFleet(const tagInfo& info) {
    if (selectedLandingX == -1 || selectedLandingY == -1) {
        this->DebugText("No landing position selected");
        return;
    }

    // 处理所有运输船
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) {  // 运输船
            this->DebugText("Transport #" + to_string(farmer.SN) +
                          " at (" + to_string(farmer.BlockDR) + "," + to_string(farmer.BlockUR) +
                          ") state=" + to_string(farmer.NowState) +
                          " villagers=" + to_string(farmer.Resource));

            // 计算到登陆点的距离
            int distToLanding = abs(farmer.BlockDR - selectedLandingX) +
                               abs(farmer.BlockUR - selectedLandingY);

            // 情况1：船上有村民，需要送到敌方大陆
            if (farmer.Resource > 0) {
                if (farmer.NowState == HUMAN_STATE_IDLE) {
                    // 关键点：确保selectedLandingX/Y是靠海的陆地坐标
                    // scanForEnemyContinent应该已经选择了靠海的陆地
                    int ret = HumanMove(farmer.SN,
                                      selectedLandingX * BLOCKSIDELENGTH,
                                      selectedLandingY * BLOCKSIDELENGTH);
                    this->DebugText("Transport with " + to_string(farmer.Resource) +
                                  " villagers moving to landing position (" +
                                  to_string(selectedLandingX) + "," +
                                  to_string(selectedLandingY) + "), distance=" +
                                  to_string(distToLanding) + ", ret=" + to_string(ret));

                    // 如果非常接近登陆点
                    if (distToLanding <= 2) {
                        this->DebugText("Transport near landing zone, villagers should auto-disembark");
                    }
                }
            }
            // 情况2：船是空的
            else if (farmer.Resource == 0) {
                int distFromHome = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);

                // 如果在敌方大陆附近（空船），返回本土
                if (distFromHome > 40) {
                    if (farmer.NowState == HUMAN_STATE_IDLE) {
                        // 寻找本土附近的海洋位置（保持原有逻辑）
                        int homeX = -1, homeY = -1;
                        double minDist = 999999;

                        for (int dx = -15; dx <= 15; dx++) {
                            for (int dy = -15; dy <= 15; dy++) {
                                int checkX = center_x + dx;
                                int checkY = center_y + dy;

                                if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                                    if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                        // 检查是否靠近陆地
                                        bool nearLand = false;
                                        for (int ddx = -1; ddx <= 1; ddx++) {
                                            for (int ddy = -1; ddy <= 1; ddy++) {
                                                int landX = checkX + ddx;
                                                int landY = checkY + ddy;
                                                if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                                                    if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                                        nearLand = true;
                                                        break;
                                                    }
                                                }
                                            }
                                            if (nearLand) break;
                                        }

                                        if (nearLand) {
                                            double dist = sqrt(pow(checkX - farmer.BlockDR, 2) +
                                                             pow(checkY - farmer.BlockUR, 2));
                                            if (dist < minDist) {
                                                minDist = dist;
                                                homeX = checkX;
                                                homeY = checkY;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (homeX != -1 && homeY != -1) {
                            int ret = HumanMove(farmer.SN, homeX * BLOCKSIDELENGTH, homeY * BLOCKSIDELENGTH);
                            this->DebugText("Empty transport returning to home waters at (" +
                                          to_string(homeX) + "," + to_string(homeY) +
                                          "), ret=" + to_string(ret));
                        }
                    }
                } else {
                    this->DebugText("Empty transport at home, ready for loading");
                }
            }
        }
    }
}

bool UsrAI::findHomeCoastalPosition(int& x, int& y, const tagInfo& info) {
    // 在本土市镇中心附近寻找靠海的陆地
    const int searchRadius = 20;
    int bestX = -1, bestY = -1;
    double minDist = 999999;

    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int checkX = center_x + dx;
            int checkY = center_y + dy;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) continue;

            // 必须是陆地
            if ((*info.theMap)[checkX][checkY].type != MAPPATTERN_GRASS) continue;

            // 检查是否靠海
            bool isCoastal = false;
            const int offsets[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
            for (const auto& offset : offsets) {
                int adjX = checkX + offset[0];
                int adjY = checkY + offset[1];
                if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                    if ((*info.theMap)[adjX][adjY].type == MAPPATTERN_OCEAN) {
                        isCoastal = true;
                        break;
                    }
                }
            }

            if (isCoastal) {
                double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                if (dist < minDist) {
                    minDist = dist;
                    bestX = checkX;
                    bestY = checkY;
                }
            }
        }
    }

    if (bestX != -1) {
        x = bestX;
        y = bestY;
        return true;
    }
    return false;
}

void UsrAI::manageCombat(const tagInfo& info) {
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) continue;
        if (army.NowState != HUMAN_STATE_IDLE) continue;

        int nearestEnemySN = -1;
        double minDist = 999999;

        for (const auto& enemy : info.enemy_armies) {
            double dist = sqrt(pow(army.BlockDR - enemy.BlockDR, 2) +
                             pow(army.BlockUR - enemy.BlockUR, 2));
            if (dist < minDist) {
                minDist = dist;
                nearestEnemySN = enemy.SN;
            }
        }

        for (const auto& enemy : info.enemy_buildings) {
            if (enemy.Type == BUILDING_ARROWTOWER) {
                double dist = sqrt(pow(army.BlockDR - enemy.BlockDR, 2) +
                                 pow(army.BlockUR - enemy.BlockUR, 2));
                if (dist < minDist) {
                    minDist = dist;
                    nearestEnemySN = enemy.SN;
                }
            }
        }

        if (nearestEnemySN != -1 && minDist < 20) {
            HumanAction(army.SN, nearestEnemySN);
            this->DebugText("Army #" + to_string(army.SN) + " attacking enemy #" + to_string(nearestEnemySN));
        }
    }
}

// 在collectGoldPhase函数中调用村民运输逻辑
void UsrAI::collectGoldPhase(const tagInfo& info) {
    this->DebugText("=== Gold Collection ===");

    goldCollected = info.Gold;
    this->DebugText("Gold: " + to_string(goldCollected) + "/" + to_string(TARGET_GOLD));

    if (goldCollected >= TARGET_GOLD) {
        this->DebugText("=== VICTORY! Collected " + to_string(goldCollected) + " gold! ===");
        return;
    }

    // 更新已运输的村民计数
    villagersTransported = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 40) {
                villagersTransported++;
            }
        }
    }

    this->DebugText("Villagers on enemy continent: " + to_string(villagersTransported));

    // 如果村民不够，运输更多村民
    if (villagersTransported < TARGET_GOLD_MINERS) {
        loadVillagersOntoTransports(info);

        // 指挥运输船前往敌方大陆
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 1 && farmer.Resource > 0) {
                if (selectedLandingX != -1 && selectedLandingY != -1) {
                    HumanMove(farmer.SN, selectedLandingX * BLOCKSIDELENGTH,
                            selectedLandingY * BLOCKSIDELENGTH);
                    this->DebugText("Transport #" + to_string(farmer.SN) + " heading to enemy continent");
                }
            }
        }
    }

    // 原有的金矿收集逻辑
    if (!goldPositions.empty()) {
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist > 40) {
                    int nearestGoldSN = -1;
                    double minDist = 999999;
                    for (const auto& res : info.resources) {
                        if (res.Type == RESOURCE_GOLD && res.Cnt > 0) {
                            double d = abs(farmer.BlockDR - res.BlockDR) + abs(farmer.BlockUR - res.BlockUR);
                            if (d < minDist) {
                                minDist = d;
                                nearestGoldSN = res.SN;
                            }
                        }
                    }

                    if (nearestGoldSN != -1) {
                        HumanAction(farmer.SN, nearestGoldSN);
                        goldMiners.insert(farmer.SN);
                        this->DebugText("Villager #" + to_string(farmer.SN) + " -> Gold");
                    }
                }
            }
        }
    }

    this->protectGoldMiners(info);
    this->manageCombat(info);
    this->assignTasksToVillagersWithLimits(info, false);
}

void UsrAI::transportVillagersToGold(const tagInfo& info) {
    int villagersOnEnemyContinent = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 40) {
                villagersOnEnemyContinent++;
            }
        }
    }

    this->DebugText("Gold miners on enemy continent: " + to_string(villagersOnEnemyContinent) + "/" + to_string(TARGET_GOLD_MINERS));

    if (villagersOnEnemyContinent < TARGET_GOLD_MINERS) {
        int totalVillagers = 0;
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0) totalVillagers++;
        }

        if (totalVillagers < 25 && info.Meat >= BUILDING_CENTER_CREATEFARMER_FOOD) {
            for (const auto& building : info.buildings) {
                if (building.Type == BUILDING_CENTER && building.Percent == 100 && building.Project == 0) {
                    if ((info.farmers.size() + info.armies.size()) < info.Human_MaxNum) {
                        int ret = BuildingAction(building.SN, BUILDING_CENTER_CREATEFARMER);
                        if (ret > 0) {
                            this->DebugText("Producing villager for gold mining");
                            return;
                        }
                    }
                }
            }
        }

        std::vector<int> homeVillagers;
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist < 30) {
                    if (farmer.NowState == HUMAN_STATE_IDLE) {
                        homeVillagers.push_back(farmer.SN);
                    } else if (farmer.NowState == HUMAN_STATE_WORKING) {
                        bool isCritical = false;
                        for (const auto& res : info.resources) {
                            if (res.SN == farmer.WorkObjectSN) {
                                if (res.Type == RESOURCE_TREE && info.Wood < 200) {
                                    isCritical = true;
                                }
                                break;
                            }
                        }
                        if (!isCritical) {
                            HumanMove(farmer.SN, farmer.DR, farmer.UR);
                            homeVillagers.push_back(farmer.SN);
                        }
                    }
                }
            }
        }

        this->DebugText("Available villagers for transport: " + to_string(homeVillagers.size()));

        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 1) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist < 30 && farmer.Resource < 5) {
                    int loaded = 0;
                    for (int villagerSN : homeVillagers) {
                        if (farmer.Resource + loaded >= 5) break;
                        HumanAction(villagerSN, farmer.SN);
                        this->DebugText("Loading villager #" + to_string(villagerSN));
                        loaded++;
                    }
                }

                if (farmer.Resource > 0 && !goldPositions.empty()) {
                    if (selectedLandingX != -1 && selectedLandingY != -1) {
                        HumanMove(farmer.SN, selectedLandingX * BLOCKSIDELENGTH,
                                selectedLandingY * BLOCKSIDELENGTH);
                        this->DebugText("Transport #" + to_string(farmer.SN) + " heading to gold");
                    }
                }
            }
        }

        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 1 && farmer.Resource == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist > 40) {
                    int coastX, coastY;
                    if (findCoastalLandingPosition(coastX, coastY, info)) {
                        HumanMove(farmer.SN, coastX * BLOCKSIDELENGTH, coastY * BLOCKSIDELENGTH);
                        this->DebugText("Empty transport returning home");
                    }
                }
            }
        }
    }
}

void UsrAI::protectGoldMiners(const tagInfo& info) {
    if (goldPositions.empty()) return;

    int goldX = goldPositions[0].first;
    int goldY = goldPositions[0].second;

    int radius = 5;
    int unitCount = 0;

    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) continue;
        if (army.NowState != HUMAN_STATE_IDLE) continue;

        double angle = (unitCount * 2 * 3.14159) / 8;
        int targetX = goldX + (int)(radius * cos(angle));
        int targetY = goldY + (int)(radius * sin(angle));

        if (targetX >= 0 && targetX < 128 && targetY >= 0 && targetY < 128) {
            HumanMove(army.SN, targetX * BLOCKSIDELENGTH, targetY * BLOCKSIDELENGTH);
            unitCount++;
        }
    }
}

bool UsrAI::findSafeLandingPosition(int& x, int& y, const tagInfo& info) {
    double maxSafety = -1;
    int bestX = -1, bestY = -1;

    for (const auto& pos : landingPositions) {
        double minEnemyDist = 999999;

        for (const auto& enemy : info.enemy_armies) {
            double dist = sqrt(pow(pos.first - enemy.BlockDR, 2) +
                             pow(pos.second - enemy.BlockUR, 2));
            if (dist < minEnemyDist) {
                minEnemyDist = dist;
            }
        }

        if (minEnemyDist > maxSafety) {
            maxSafety = minEnemyDist;
            bestX = pos.first;
            bestY = pos.second;
        }
    }

    if (bestX != -1) {
        x = bestX;
        y = bestY;
        return true;
    }

    return false;
}

// Part 7: Main Process Loop

void UsrAI::processData() {
    tagInfo info = getInfo();

    // Update counts
    houseCount = 0;
    housesUnderConstruction = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_HOME) {
            if (b.Percent == 100) houseCount++;
            else housesUnderConstruction++;
        }
    }

    stockBuilt = false;
    dockBuilt = false;
    dockConstructionStarted = false;
    totalDocksPresent = 0;
    completedDocksCount = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) stockBuilt = true;
        if (b.Type == BUILDING_DOCK) {
            totalDocksPresent++;
            if (b.Percent == 100) {
                dockBuilt = true;
                completedDocksCount++;
            }
            if (b.Percent < 100) dockConstructionStarted = true;
        }
    }

    fishingBoatCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2) fishingBoatCount++;
    }

    warshipCount = 0;
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) warshipCount++;
    }

    transportShipCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) transportShipCount++;
    }

    if (!upgradeStarted) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_CENTER && building.Project == BUILDING_CENTER_UPGRADE) {
                upgradeStarted = true;
                this->DebugText("=== Age upgrade in progress ===");

                // 修复：不强制召回村民，避免产生WALKING状态
                // 让村民自然完成当前工作，升级完成后再重新分配
                // 原有的强制召回会导致村民进入WALKING状态，影响后续建造者分配

                // 可选：只清空普通村民集合，让升级后重新分配
                ordinaryVillagers.clear();
                this->DebugText("Cleared ordinary villagers set for post-upgrade reassignment");

                break;
            }
        }
    }

    // 添加：检测工具时代建造者是否完成任务
    if (toolAgeBuilderSN != -1 && toolAgeBuilderBusy) {
        bool builderStillBusy = false;

        for (const auto& farmer : info.farmers) {
            if (farmer.SN == toolAgeBuilderSN) {
                // 如果建造者不是空闲状态，说明还在工作
                if (farmer.NowState != HUMAN_STATE_IDLE) {
                    builderStillBusy = true;
                }
                break;
            }
        }

        // 如果建造者变为空闲，重置忙碌状态
        if (!builderStillBusy) {
            toolAgeBuilderBusy = false;
            this->DebugText("Tool age builder #" + to_string(toolAgeBuilderSN) + " completed task, now available");
        }
    }

    // 检查升级完成
    if (upgradeStarted && info.civilizationStage == CIVILIZATION_TOOLAGE) {
        this->DebugText("=== Age upgrade completed, entering Tool Age ===");
        upgradeStarted = false;
        toolAgeInitialized = false; // 确保工具时代逻辑重新初始化

        // 设置升级后的参数
        villagersToProduceAfterUpgrade = 6;
        villagersProducedAfterUpgrade = 0;
        currentStage = STAGE_AFTER_UPGRADE;
    }

    // 升级期间的简单资源收集
    if (upgradeStarted) {
        this->assignTasksToVillagersWithLimits(info, false);
    }

    this->DebugText("Stage: " + to_string(currentStage));

    // Main stage management
    switch(currentStage) {
        case STAGE_INITIAL:
            if (!centerInitialized) this->initializeCenter(info);
            break;

        case STAGE_BUILD_HOUSES:
            this->buildHousesPhase(info);
            break;

        case STAGE_POPULATION_GROWTH:
            this->populationGrowthPhase(info);
            break;

        case STAGE_COLLECT_RESOURCES:
            this->collectResourcesPhase(info);
            break;

        case STAGE_BUILD_REQUIRED_BUILDINGS:
            this->buildRequiredBuildingsPhase(info);
            break;

        case STAGE_UPGRADE_AGE:
            this->upgradeAgePhase(info);
            break;

        case STAGE_BUILD_FISHING_BOAT:
            this->buildFishingBoatPhase(info);
            break;

        case STAGE_AFTER_UPGRADE:
            if (!upgradeStarted) {
                this->afterUpgradePhase(info);
            }
            break;

        case STAGE_BUILD_WARSHIPS:
            this->buildWarshipsPhase(info);
            break;

        case STAGE_BUILD_ARMY:
            this->buildArmyPhase(info);
            break;

        case STAGE_LAND_INVASION:
            this->landInvasionPhase(info);
            break;

        case STAGE_COLLECT_GOLD:
            this->collectGoldPhase(info);
            break;

        case STAGE_EXPLORE:
            this->explorePhase(info);
            break;
    }

    // Parallel tasks that run in multiple stages
    if (currentStage >= STAGE_BUILD_ARMY) {
        this->manageTransportShipProduction(info);
    }

    // Always manage naval units
    this->assignFishingBoatsToFishResources(info);
    this->assignTransportShipsToShore(info);

    prevInfo = info;
}

bool UsrAI::findHomeCoastalLandPosition(int& x, int& y, const tagInfo& info) {
    const int searchRadius = 15;
    int bestX = -1, bestY = -1;
    double minDist = 999999;

    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int checkX = center_x + dx;
            int checkY = center_y + dy;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) continue;

            // 必须是陆地
            if ((*info.theMap)[checkX][checkY].type != MAPPATTERN_GRASS) continue;

            // 检查是否靠海
            bool isCoastal = false;
            for (int ddx = -1; ddx <= 1; ddx++) {
                for (int ddy = -1; ddy <= 1; ddy++) {
                    if (ddx == 0 && ddy == 0) continue;
                    int adjX = checkX + ddx;
                    int adjY = checkY + ddy;
                    if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                        if ((*info.theMap)[adjX][adjY].type == MAPPATTERN_OCEAN) {
                            isCoastal = true;
                            break;
                        }
                    }
                }
                if (isCoastal) break;
            }

            if (isCoastal) {
                // 选择最近的靠海陆地
                double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                if (dist < minDist) {
                    minDist = dist;
                    bestX = checkX;
                    bestY = checkY;
                }
            }
        }
    }

    if (bestX != -1) {
        x = bestX;
        y = bestY;
        return true;
    }
    return false;
}
